Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix Even More Issues #1559

Merged
merged 9 commits into from
Jan 16, 2025
Merged
Show file tree
Hide file tree
Changes from 4 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
123 changes: 81 additions & 42 deletions Content.Server/Shuttles/Systems/ArrivalsSystem.cs
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
using System.Linq;
using System.Numerics;
using Content.Server.Administration;
using Content.Server.Chat.Managers;
using Content.Server.DeviceNetwork.Components;
using Content.Server.DeviceNetwork.Systems;
using Content.Server.GameTicking;
Expand All @@ -16,12 +17,13 @@
using Content.Server.Station.Systems;
using Content.Shared.Administration;
using Content.Shared.CCVar;
using Content.Shared.Damage.Components;
using Content.Shared.DeviceNetwork;
using Content.Shared.GameTicking;
using Content.Shared.Mobs.Components;
using Content.Shared.Movement.Components;
using Content.Shared.Parallax.Biomes;
using Content.Shared.Roles;
using Content.Shared.Preferences;
using Content.Shared.Salvage;
using Content.Shared.Shuttles.Components;
using Content.Shared.Tiles;
Expand All @@ -30,6 +32,7 @@
using Robust.Shared.Configuration;
using Robust.Shared.Console;
using Robust.Shared.Map;
using Robust.Shared.Player;
using Robust.Shared.Prototypes;
using Robust.Shared.Random;
using Robust.Shared.Timing;
Expand All @@ -45,17 +48,20 @@ public sealed class ArrivalsSystem : EntitySystem
[Dependency] private readonly IConfigurationManager _cfgManager = default!;
[Dependency] private readonly IConsoleHost _console = default!;
[Dependency] private readonly IGameTiming _timing = default!;
[Dependency] private readonly IMapManager _mapManager = default!;
[Dependency] private readonly IPrototypeManager _protoManager = default!;
[Dependency] private readonly IRobustRandom _random = default!;
[Dependency] private readonly IChatManager _chat = default!;
[Dependency] private readonly SharedMapSystem _mapSystem = default!;
[Dependency] private readonly BiomeSystem _biomes = default!;
[Dependency] private readonly GameTicker _ticker = default!;
[Dependency] private readonly MapLoaderSystem _loader = default!;
[Dependency] private readonly MetaDataSystem _metaData = default!;
[Dependency] private readonly DeviceNetworkSystem _deviceNetworkSystem = default!;
[Dependency] private readonly SharedTransformSystem _transform = default!;
[Dependency] private readonly ShuttleSystem _shuttles = default!;
[Dependency] private readonly StationSpawningSystem _stationSpawning = default!;
[Dependency] private readonly StationSystem _station = default!;
[Dependency] private readonly ActorSystem _actor = default!;

private EntityQuery<PendingClockInComponent> _pendingQuery;
private EntityQuery<ArrivalsBlacklistComponent> _blacklistQuery;
Expand Down Expand Up @@ -87,7 +93,7 @@ public override void Initialize()
{
base.Initialize();

SubscribeLocalEvent<PlayerSpawningEvent>(HandlePlayerSpawning, before: new []{ typeof(ContainerSpawnPointSystem), typeof(SpawnPointSystem)});
SubscribeLocalEvent<PlayerSpawningEvent>(HandlePlayerSpawning, before: new []{ typeof(SpawnPointSystem)}, after: new [] { typeof(ContainerSpawnPointSystem)});

SubscribeLocalEvent<StationArrivalsComponent, StationPostInitEvent>(OnStationPostInit);

Expand All @@ -98,6 +104,8 @@ public override void Initialize()
SubscribeLocalEvent<ArrivalsShuttleComponent, FTLStartedEvent>(OnArrivalsFTL);
SubscribeLocalEvent<ArrivalsShuttleComponent, FTLCompletedEvent>(OnArrivalsDocked);

SubscribeLocalEvent<PlayerSpawnCompleteEvent>(SendDirections);

_pendingQuery = GetEntityQuery<PendingClockInComponent>();
_blacklistQuery = GetEntityQuery<ArrivalsBlacklistComponent>();
_mobQuery = GetEntityQuery<MobStateComponent>();
Expand Down Expand Up @@ -263,6 +271,9 @@ private void OnArrivalsFTL(EntityUid shuttleUid, ArrivalsShuttleComponent compon
// The player has successfully left arrivals and is also not on the shuttle. Remove their warp coupon.
RemCompDeferred<PendingClockInComponent>(pUid);
RemCompDeferred<AutoOrientComponent>(pUid);

if (ArrivalsGodmode)
RemCompDeferred<GodmodeComponent>(pUid);
}
}

Expand All @@ -287,16 +298,20 @@ private void OnArrivalsDocked(EntityUid uid, ArrivalsShuttleComponent component,
private void DumpChildren(EntityUid uid, ref FTLStartedEvent args)
{
var toDump = new List<Entity<TransformComponent>>();
DumpChildren(uid, ref args, toDump);
FindDumpChildren(uid, toDump);
foreach (var (ent, xform) in toDump)
{
var rotation = xform.LocalRotation;
_transform.SetCoordinates(ent, new EntityCoordinates(args.FromMapUid!.Value, Vector2.Transform(xform.LocalPosition, args.FTLFrom)));
_transform.SetWorldRotation(ent, args.FromRotation + rotation);
if (_actor.TryGetSession(ent, out var session))
{
_chat.DispatchServerMessage(session!, Loc.GetString("latejoin-arrivals-dumped-from-shuttle"));
}
sleepyyapril marked this conversation as resolved.
Show resolved Hide resolved
}
}

private void DumpChildren(EntityUid uid, ref FTLStartedEvent args, List<Entity<TransformComponent>> toDump)
private void FindDumpChildren(EntityUid uid, List<Entity<TransformComponent>> toDump)
{
if (_pendingQuery.HasComponent(uid))
return;
Expand All @@ -312,7 +327,7 @@ private void DumpChildren(EntityUid uid, ref FTLStartedEvent args, List<Entity<T
var children = xform.ChildEnumerator;
while (children.MoveNext(out var child))
{
DumpChildren(child, ref args, toDump);
FindDumpChildren(child, toDump);
}
}

Expand All @@ -321,8 +336,7 @@ public void HandlePlayerSpawning(PlayerSpawningEvent ev)
if (ev.SpawnResult != null)
return;

if (ev.HumanoidCharacterProfile?.SpawnPriority != SpawnPriorityPreference.Arrivals)
return;
// We use arrivals as the default spawn so don't check for job prio.

// Only works on latejoin even if enabled.
if (!Enabled || _ticker.RunLevel != GameRunLevel.InRound)
Expand All @@ -333,39 +347,56 @@ public void HandlePlayerSpawning(PlayerSpawningEvent ev)
&& _protoManager.Index<JobPrototype>(ev.Job.Prototype.Value.Id).AlwaysUseSpawner)
return;


if (!HasComp<StationArrivalsComponent>(ev.Station))
return;

TryGetArrivals(out var arrivals);

if (TryComp<TransformComponent>(arrivals, out var arrivalsXform))
{
var mapId = arrivalsXform.MapID;
if (!TryComp(arrivals, out TransformComponent? arrivalsXform))
return;

var points = EntityQueryEnumerator<SpawnPointComponent, TransformComponent>();
var possiblePositions = new List<EntityCoordinates>();
while (points.MoveNext(out var uid, out var spawnPoint, out var xform))
{
if (spawnPoint.SpawnType != SpawnPointType.LateJoin || xform.MapID != mapId)
continue;
var mapId = arrivalsXform.MapID;

possiblePositions.Add(xform.Coordinates);
}
var points = EntityQueryEnumerator<SpawnPointComponent, TransformComponent>();
var possiblePositions = new List<EntityCoordinates>();
while (points.MoveNext(out var uid, out var spawnPoint, out var xform))
{
if (spawnPoint.SpawnType != SpawnPointType.LateJoin || xform.MapID != mapId)
continue;

if (possiblePositions.Count > 0)
{
var spawnLoc = _random.Pick(possiblePositions);
ev.SpawnResult = _stationSpawning.SpawnPlayerMob(
spawnLoc,
ev.Job,
ev.HumanoidCharacterProfile,
ev.Station);

EnsureComp<PendingClockInComponent>(ev.SpawnResult.Value);
EnsureComp<AutoOrientComponent>(ev.SpawnResult.Value);
}
possiblePositions.Add(xform.Coordinates);
}

if (possiblePositions.Count <= 0)
return;

var spawnLoc = _random.Pick(possiblePositions);
ev.SpawnResult = _stationSpawning.SpawnPlayerMob(
spawnLoc,
ev.Job,
ev.HumanoidCharacterProfile,
ev.Station);

EnsureComp<PendingClockInComponent>(ev.SpawnResult.Value);
EnsureComp<AutoOrientComponent>(ev.SpawnResult.Value);

// If you're forced to spawn, you're invincible until you leave wherever you were forced to spawn.
if (ArrivalsGodmode)
EnsureComp<GodmodeComponent>(ev.SpawnResult.Value);
}

private void SendDirections(PlayerSpawnCompleteEvent ev)
{
if (!Enabled || !ev.LateJoin || !_pendingQuery.HasComp(ev.Mob))
return;

var arrival = NextShuttleArrival();

var message = arrival is not null
? Loc.GetString("latejoin-arrivals-direction-time", ("time", $"{arrival:mm\\:ss}"))
: Loc.GetString("latejoin-arrivals-direction");

_chat.DispatchServerMessage(ev.Player, message);
}

private bool TryTeleportToMapSpawn(EntityUid player, EntityUid stationId, TransformComponent? transform = null)
Expand All @@ -391,6 +422,10 @@ private bool TryTeleportToMapSpawn(EntityUid player, EntityUid stationId, Transf
{
// Move the player to a random late-join spawnpoint.
_transform.SetCoordinates(player, transform, _random.Pick(possiblePositions));
if (_actor.TryGetSession(player, out var session))
{
_chat.DispatchServerMessage(session!, Loc.GetString("latejoin-arrivals-teleport-to-spawn"));
}
sleepyyapril marked this conversation as resolved.
Show resolved Hide resolved
return true;
}

Expand Down Expand Up @@ -436,7 +471,7 @@ public override void Update(float frameTime)
var curTime = _timing.CurTime;
TryGetArrivals(out var arrivals);

if (TryComp<TransformComponent>(arrivals, out var arrivalsXform))
if (TryComp(arrivals, out TransformComponent? arrivalsXform))
{
while (query.MoveNext(out var uid, out var comp, out var shuttle, out var xform))
{
Expand All @@ -449,7 +484,7 @@ public override void Update(float frameTime)
if (xform.MapUid != arrivalsXform.MapUid)
{
if (arrivals.IsValid())
_shuttles.FTLToDock(uid, shuttle, arrivals, _cfgManager.GetCVar(CCVars.ArrivalsStartupTime), _cfgManager.GetCVar(CCVars.ArrivalsHyperspaceTime), "DockArrivals");
_shuttles.FTLToDock(uid, shuttle, arrivals);

comp.NextArrivalsTime = _timing.CurTime + TimeSpan.FromSeconds(tripTime);
}
Expand All @@ -459,7 +494,7 @@ public override void Update(float frameTime)
var targetGrid = _station.GetLargestGrid(data);

if (targetGrid != null)
_shuttles.FTLToDock(uid, shuttle, targetGrid.Value, _cfgManager.GetCVar(CCVars.ArrivalsStartupTime), _cfgManager.GetCVar(CCVars.ArrivalsHyperspaceTime), "DockArrivals");
_shuttles.FTLToDock(uid, shuttle, targetGrid.Value);

// The ArrivalsCooldown includes the trip there, so we only need to add the time taken for
// the trip back.
Expand All @@ -483,9 +518,8 @@ private void OnRoundStarting(RoundStartingEvent ev)

private void SetupArrivalsStation()
{
var mapId = _mapManager.CreateMap();
var mapUid = _mapManager.GetMapEntityId(mapId);
_mapManager.AddUninitializedMap(mapId);
var mapUid = _mapSystem.CreateMap(out var mapId, false);
_metaData.SetEntityName(mapUid, Loc.GetString("map-name-terminal"));

if (!_loader.TryLoad(mapId, _cfgManager.GetCVar(CCVars.ArrivalsMap), out var uids))
{
Expand All @@ -504,9 +538,14 @@ private void SetupArrivalsStation()
{
var template = _random.Pick(_arrivalsBiomeOptions);
_biomes.EnsurePlanet(mapUid, _protoManager.Index(template));
var restricted = new RestrictedRangeComponent
{
Range = 32f
};
AddComp(mapUid, restricted);
}

_mapManager.DoMapInitialize(mapId);
_mapSystem.InitializeMap(mapId);

// Handle roundstart stations.
var query = AllEntityQuery<StationArrivalsComponent>();
Expand Down Expand Up @@ -564,10 +603,10 @@ private void SetupShuttle(EntityUid uid, StationArrivalsComponent component)
return;

// Spawn arrivals on a dummy map then dock it to the source.
var dummyMap = _mapManager.CreateMap();
var dummpMapEntity = _mapSystem.CreateMap(out var dummyMapId);

if (TryGetArrivals(out var arrivals) &&
_loader.TryLoad(dummyMap, component.ShuttlePath.ToString(), out var shuttleUids))
_loader.TryLoad(dummyMapId, component.ShuttlePath.ToString(), out var shuttleUids))
{
component.Shuttle = shuttleUids[0];
var shuttleComp = Comp<ShuttleComponent>(component.Shuttle);
Expand All @@ -579,7 +618,7 @@ private void SetupShuttle(EntityUid uid, StationArrivalsComponent component)
}

// Don't start the arrivals shuttle immediately docked so power has a time to stabilise?
var timer = AddComp<TimedDespawnComponent>(_mapManager.GetMapEntityId(dummyMap));
var timer = AddComp<TimedDespawnComponent>(dummpMapEntity);
timer.Lifetime = 15f;
}
}
10 changes: 10 additions & 0 deletions Content.Shared/Bed/Cryostorage/CanEnterCryostorageComponent.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
using Robust.Shared.GameStates;

namespace Content.Shared.Bed.Cryostorage;

/// <summary>
/// Serves as a whitelist that allows an entity with this component to enter cryostorage.
/// It will also require MindContainerComponent.
/// </summary>
[RegisterComponent, NetworkedComponent]
public sealed partial class CanEnterCryostorageComponent : Component { }
2 changes: 1 addition & 1 deletion Content.Shared/Bed/Cryostorage/SharedCryostorageSystem.cs
Original file line number Diff line number Diff line change
Expand Up @@ -89,7 +89,7 @@ private void OnInsertAttempt(Entity<CryostorageComponent> ent, ref ContainerIsIn
return;
}

if (!TryComp<MindContainerComponent>(args.EntityUid, out var mindContainer))
if (!HasComp<CanEnterCryostorageComponent>(args.EntityUid) || !TryComp<MindContainerComponent>(args.EntityUid, out var mindContainer))
{
args.Cancel();
return;
Expand Down
10 changes: 4 additions & 6 deletions Content.Shared/InteractionVerbs/SharedInteractionVerbsSystem.cs
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
using Content.Shared.Contests;
using Content.Shared.DoAfter;
using Content.Shared.Ghost;
using Content.Shared.IdentityManagement;
using Content.Shared.Interaction;
using Content.Shared.InteractionVerbs.Events;
using Content.Shared.Popups;
Expand All @@ -27,17 +28,14 @@ public abstract class SharedInteractionVerbsSystem : EntitySystem
private readonly InteractionAction.VerbDependencies _verbDependencies = new();
private List<InteractionVerbPrototype> _globalPrototypes = default!;

[Dependency] private readonly ActionBlockerSystem _actionBlocker = default!;
[Dependency] private readonly SharedAudioSystem _audio = default!;
[Dependency] private readonly SharedDoAfterSystem _doAfters = default!;
[Dependency] private readonly SharedContainerSystem _containers = default!;
[Dependency] private readonly ContestsSystem _contests = default!;
[Dependency] private readonly SharedInteractionSystem _interactions = default!;
[Dependency] private readonly INetManager _net = default!;
[Dependency] private readonly SharedPopupSystem _popups = default!;
[Dependency] private readonly IPrototypeManager _protoMan = default!;
[Dependency] private readonly IGameTiming _timing = default!;
[Dependency] private readonly EntityWhitelistSystem _whitelistSystem = default!;
[Dependency] private readonly IEntityManager _entityManager = default!;

public override void Initialize()
{
Expand Down Expand Up @@ -385,8 +383,8 @@ private void CreateVerbEffects(InteractionVerbPrototype.EffectSpecifier? specifi

(string, object)[] localeArgs =
[
("user", user),
("target", target),
("user", Identity.Entity(user, _entityManager)),
("target", Identity.Entity(target, _entityManager)),
("used", used ?? EntityUid.Invalid),
("selfTarget", user == target),
("hasUsed", used != null)
Expand Down
6 changes: 6 additions & 0 deletions Resources/Prototypes/Entities/Mobs/Species/base.yml
Original file line number Diff line number Diff line change
Expand Up @@ -187,6 +187,12 @@
- type: Scent
- type: MindContainer
showExamineInfo: true
- type: CanEnterCryostorage
- type: InteractionPopup
successChance: 1
interactSuccessString: hugging-success-generic
interactSuccessSound: /Audio/Effects/thudswoosh.ogg
messagePerceivedByOthers: hugging-success-generic-others
- type: CanHostGuardian
- type: NpcFactionMember
factions:
Expand Down
Loading