Skip to content

Commit

Permalink
Merge pull request #263 from Rxup/upstream-sync
Browse files Browse the repository at this point in the history
Upstream sync
  • Loading branch information
KayzelW authored Oct 7, 2023
2 parents b562789 + a180377 commit c279c6c
Show file tree
Hide file tree
Showing 381 changed files with 26,438 additions and 42,965 deletions.
8 changes: 8 additions & 0 deletions Content.IntegrationTests/Pair/TestPair.cs
Original file line number Diff line number Diff line change
@@ -1,7 +1,12 @@
#nullable enable
using System.Collections.Generic;
using System.IO;
using System.Linq;
using Content.Server.GameTicking;
using Content.Server.Players;
using Content.Shared.Mind;
using Content.Shared.Players;
using Robust.Server.Player;
using Robust.Shared.GameObjects;
using Robust.Shared.IoC;
using Robust.Shared.Network;
Expand All @@ -25,6 +30,9 @@ public sealed partial class TestPair
public RobustIntegrationTest.ServerIntegrationInstance Server { get; private set; } = default!;
public RobustIntegrationTest.ClientIntegrationInstance Client { get; private set; } = default!;

public IPlayerSession? Player => (IPlayerSession?) Server.PlayerMan.Sessions.FirstOrDefault();
public PlayerData? PlayerData => Player?.Data.ContentData();

public PoolTestLogHandler ServerLogHandler { get; private set; } = default!;
public PoolTestLogHandler ClientLogHandler { get; private set; } = default!;

Expand Down
71 changes: 71 additions & 0 deletions Content.IntegrationTests/Tests/ConfigPresetTests.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
using System.Collections.Generic;
using System.IO;
using Content.Server.Entry;
using Robust.Shared.Configuration;
using Robust.Shared.ContentPack;

namespace Content.IntegrationTests.Tests;

[TestFixture]
public sealed class ConfigPresetTests
{
[Test]
public async Task TestLoadAll()
{
var pair = await PoolManager.GetServerClient();
var server = pair.Server;

var resources = server.ResolveDependency<IResourceManager>();
var config = server.ResolveDependency<IConfigurationManager>();

await server.WaitPost(() =>
{
var originalCVars = new List<(string, object)>();
foreach (var cvar in config.GetRegisteredCVars())
{
var value = config.GetCVar<object>(cvar);
originalCVars.Add((cvar, value));
}

var originalCvarsStream = new MemoryStream();
config.SaveToTomlStream(originalCvarsStream, config.GetRegisteredCVars());
originalCvarsStream.Position = 0;

var presets = resources.ContentFindFiles(EntryPoint.ConfigPresetsDir);
Assert.Multiple(() =>
{
foreach (var preset in presets)
{
var stream = resources.ContentFileRead(preset);
Assert.DoesNotThrow(() => config.LoadDefaultsFromTomlStream(stream));
}
});

config.LoadDefaultsFromTomlStream(originalCvarsStream);

foreach (var originalCVar in originalCVars)
{
var (name, originalValue) = originalCVar;
var newValue = config.GetCVar<object>(name);
var originalValueType = originalValue.GetType();
var newValueType = newValue.GetType();
if (originalValueType.IsEnum || newValueType.IsEnum)
{
originalValue = Enum.ToObject(originalValueType, originalValue);
newValue = Enum.ToObject(originalValueType, newValue);
}

if (originalValueType == typeof(float) || newValueType == typeof(float))
{
originalValue = Convert.ToSingle(originalValue);
newValue = Convert.ToSingle(newValue);
}

if (!Equals(newValue, originalValue))
Assert.Fail($"CVar {name} was not reset to its original value.");
}
});

await pair.CleanReturnAsync();
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
#nullable enable
using Robust.Shared.Console;
using Robust.Shared.Map;

namespace Content.IntegrationTests.Tests.Minds;

[TestFixture]
public sealed partial class MindTests
{
[Test]
public async Task DeleteAllThenGhost()
{
var settings = new PoolSettings
{
Dirty = true,
DummyTicker = false,
Connected = true
};
await using var pair = await PoolManager.GetServerClient(settings);

// Client is connected with a valid entity & mind
Assert.That(pair.Client.EntMan.EntityExists(pair.Client.Player?.ControlledEntity));
Assert.That(pair.Server.EntMan.EntityExists(pair.PlayerData?.Mind));

// Delete **everything**
var conHost = pair.Server.ResolveDependency<IConsoleHost>();
await pair.Server.WaitPost(() => conHost.ExecuteCommand("entities delete"));
await pair.RunTicksSync(5);

Assert.That(pair.Server.EntMan.EntityCount, Is.EqualTo(0));
Assert.That(pair.Client.EntMan.EntityCount, Is.EqualTo(0));

// Create a new map.
int mapId = 1;
await pair.Server.WaitPost(() => conHost.ExecuteCommand($"addmap {mapId}"));
await pair.RunTicksSync(5);

// Client is not attached to anything
Assert.Null(pair.Client.Player?.ControlledEntity);
Assert.Null(pair.PlayerData?.Mind);

// Attempt to ghost
var cConHost = pair.Client.ResolveDependency<IConsoleHost>();
await pair.Client.WaitPost(() => cConHost.ExecuteCommand("ghost"));
await pair.RunTicksSync(10);

// Client should be attached to a ghost placed on the new map.
Assert.That(pair.Client.EntMan.EntityExists(pair.Client.Player?.ControlledEntity));
Assert.That(pair.Server.EntMan.EntityExists(pair.PlayerData?.Mind));
var xform = pair.Client.Transform(pair.Client.Player!.ControlledEntity!.Value);
Assert.That(xform.MapID, Is.EqualTo(new MapId(mapId)));

await pair.CleanReturnAsync();
}
}
47 changes: 47 additions & 0 deletions Content.Server/Anomaly/Components/InjectionAnomalyComponent.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
using Content.Server.Anomaly.Effects;
using Robust.Shared.Prototypes;

namespace Content.Server.Anomaly.Components;

/// <summary>
/// This component allows the anomaly to inject liquid from the SolutionContainer
/// into the surrounding entities with the InjectionSolution component
/// </summary>

[RegisterComponent, Access(typeof(InjectionAnomalySystem))]
public sealed partial class InjectionAnomalyComponent : Component
{
/// <summary>
/// the maximum amount of injection of a substance into an entity per pulsation
/// scales with Severity
/// </summary>
[DataField, ViewVariables(VVAccess.ReadWrite)]
public float MaxSolutionInjection = 15;
/// <summary>
/// the maximum amount of injection of a substance into an entity in the supercritical phase
/// </summary>
[DataField, ViewVariables(VVAccess.ReadWrite)]
public float SuperCriticalSolutionInjection = 50;

/// <summary>
/// The maximum radius in which the anomaly injects reagents into the surrounding containers.
/// </summary>
[DataField, ViewVariables(VVAccess.ReadWrite)]
public float InjectRadius = 3;
/// <summary>
/// The maximum radius in which the anomaly injects reagents into the surrounding containers.
/// </summary>
[DataField, ViewVariables(VVAccess.ReadWrite)]
public float SuperCriticalInjectRadius = 15;

/// <summary>
/// The name of the prototype of the special effect that appears above the entities into which the injection was carried out
/// </summary>
[DataField, ViewVariables(VVAccess.ReadOnly)]
public EntProtoId VisualEffectPrototype = "PuddleSparkle";
/// <summary>
/// Solution name that can be drained.
/// </summary>
[DataField, ViewVariables(VVAccess.ReadWrite)]
public string Solution { get; set; } = "default";
}
29 changes: 29 additions & 0 deletions Content.Server/Anomaly/Components/PuddleCreateAnomalyComponent.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
using Content.Server.Anomaly.Effects;

namespace Content.Server.Anomaly.Components;

/// <summary>
/// This component allows the anomaly to create puddles from the solutionContainer
/// </summary>
[RegisterComponent, Access(typeof(PuddleCreateAnomalySystem))]
public sealed partial class PuddleCreateAnomalyComponent : Component
{
/// <summary>
/// The maximum amount of solution that an anomaly can splash out of the storage on the floor during pulsation.
/// Scales with Severity.
/// </summary>
[DataField, ViewVariables(VVAccess.ReadWrite)]
public float MaxPuddleSize = 100;

/// <summary>
/// The maximum amount of solution that an anomaly can splash out of the storage on the floor during supercritical event
/// </summary>
[DataField, ViewVariables(VVAccess.ReadWrite)]
public float SuperCriticalPuddleSize = 1000;

/// <summary>
/// Solution name that can be drained.
/// </summary>
[DataField, ViewVariables(VVAccess.ReadWrite)]
public string Solution { get; set; } = "default";
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,94 @@
using Content.Server.Anomaly.Effects;
using Content.Shared.Chemistry.Reagent;
using Robust.Shared.Audio;
using Robust.Shared.Prototypes;
using System.Numerics;

namespace Content.Server.Anomaly.Components;
/// <summary>
/// This component allows the anomaly to generate a random type of reagent in the specified SolutionContainer.
/// With the increasing severity of the anomaly, the type of reagent produced may change.
/// The higher the severity of the anomaly, the higher the chance of dangerous or useful reagents.
/// </summary>
[RegisterComponent, Access(typeof(ReagentProducerAnomalySystem))]
public sealed partial class ReagentProducerAnomalyComponent : Component
{
//the addition of the reagent will occur instantly when an anomaly appears,
//and there will not be the first three seconds of a white empty anomaly.
public float AccumulatedFrametime = 3.0f;
/// <summary>
/// How frequently should this reagent generation update, in seconds?
/// </summary>
[DataField, ViewVariables(VVAccess.ReadWrite)]
public float UpdateInterval = 3.0f;

/// <summary>
/// The spread of the random weight of the choice of this category, depending on the severity.
/// </summary>
[DataField, ViewVariables(VVAccess.ReadWrite)]
public Vector2 WeightSpreadDangerous = new(5.0f, 9.0f);
/// <summary>
/// The spread of the random weight of the choice of this category, depending on the severity.
/// </summary>
[DataField, ViewVariables(VVAccess.ReadWrite)]
public Vector2 WeightSpreadFun = new(3.0f, 0.0f);
/// <summary>
/// The spread of the random weight of the choice of this category, depending on the severity.
/// </summary>
[DataField, ViewVariables(VVAccess.ReadWrite)]
public Vector2 WeightSpreadUseful = new(1.0f, 1.0f);

/// <summary>
/// Category of dangerous reagents for injection. Various toxins and poisons
/// </summary>
[DataField, ViewVariables(VVAccess.ReadWrite)]
public List<ProtoId<ReagentPrototype>> DangerousChemicals = new();
/// <summary>
/// Category of useful reagents for injection. Medicine and other things that players WANT to get
/// </summary>
[DataField, ViewVariables(VVAccess.ReadWrite)]
public List<ProtoId<ReagentPrototype>> UsefulChemicals = new();
/// <summary>
/// Category of fun reagents for injection. Glue, drugs, beer. Something that will bring fun.
/// </summary>
[DataField, ViewVariables(VVAccess.ReadWrite)]
public List<ProtoId<ReagentPrototype>> FunChemicals = new();

/// <summary>
/// Noise made when anomaly pulse.
/// </summary>
[DataField, ViewVariables(VVAccess.ReadWrite)]
public SoundSpecifier ChangeSound = new SoundPathSpecifier("/Audio/Effects/waterswirl.ogg");
/// <summary>
/// The component will repaint the sprites of the object to match the current color of the solution,
/// if the RandomSprite component is hung correctly.
/// Ideally, this should be put into a separate component, but I suffered for 4 hours,
/// and nothing worked out for me. So for now it will be like this.
/// </summary>
[DataField, ViewVariables(VVAccess.ReadOnly)]
public bool NeedRecolor = false;

/// <summary>
/// the maximum amount of reagent produced per second
/// </summary>
[DataField, ViewVariables(VVAccess.ReadWrite)]
public float MaxReagentProducing = 1.5f;

/// <summary>
/// how much does the reagent production increase before entering the supercritical state
/// </summary>
[DataField, ViewVariables(VVAccess.ReadWrite)]
public float SupercriticalReagentProducingModifier = 100f;

/// <summary>
/// The name of the reagent that the anomaly produces.
/// </summary>
[DataField, ViewVariables(VVAccess.ReadWrite)]
public ProtoId<ReagentPrototype> ProducingReagent = "Water";
/// <summary>
/// Solution name where the substance is generated
/// </summary>
[ViewVariables(VVAccess.ReadWrite)]
[DataField("solution")]
public string Solution = "default";
}
67 changes: 67 additions & 0 deletions Content.Server/Anomaly/Effects/InjectionAnomalySystem.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
using System.Linq;
using Content.Server.Anomaly.Components;
using Content.Server.Chemistry.Components.SolutionManager;
using Content.Server.Chemistry.EntitySystems;
using Content.Shared.Anomaly.Components;

namespace Content.Server.Anomaly.Effects;
/// <summary>
/// This component allows the anomaly to inject liquid from the SolutionContainer
/// into the surrounding entities with the InjectionSolution component
/// </summary>
///

/// <see cref="InjectionAnomalyComponent"/>
public sealed class InjectionAnomalySystem : EntitySystem
{
[Dependency] private readonly EntityLookupSystem _lookup = default!;
[Dependency] private readonly SolutionContainerSystem _solutionContainer = default!;

private EntityQuery<InjectableSolutionComponent> _injectableQuery;

public override void Initialize()
{
SubscribeLocalEvent<InjectionAnomalyComponent, AnomalyPulseEvent>(OnPulse);
SubscribeLocalEvent<InjectionAnomalyComponent, AnomalySupercriticalEvent>(OnSupercritical, before: new[] { typeof(SolutionContainerSystem) });

_injectableQuery = GetEntityQuery<InjectableSolutionComponent>();
}

private void OnPulse(EntityUid uid, InjectionAnomalyComponent component, ref AnomalyPulseEvent args)
{
PulseScalableEffect(uid, component, component.InjectRadius, component.MaxSolutionInjection * args.Severity);
}

private void OnSupercritical(EntityUid uid, InjectionAnomalyComponent component, ref AnomalySupercriticalEvent args)
{
PulseScalableEffect(uid, component, component.SuperCriticalInjectRadius, component.SuperCriticalSolutionInjection);
}

private void PulseScalableEffect(EntityUid uid, InjectionAnomalyComponent component, float injectRadius, float maxInject)
{
if (!_solutionContainer.TryGetSolution(uid, component.Solution, out var sol))
return;
//We get all the entity in the radius into which the reagent will be injected.
var xformQuery = GetEntityQuery<TransformComponent>();
var xform = xformQuery.GetComponent(uid);
var allEnts = _lookup.GetComponentsInRange<InjectableSolutionComponent>(xform.MapPosition, injectRadius)
.Select(x => x.Owner).ToList();

//for each matching entity found
foreach (var ent in allEnts)
{
if (!_solutionContainer.TryGetInjectableSolution(ent, out var injectable))
continue;

if (_injectableQuery.TryGetComponent(ent, out var injEnt))
{
var buffer = sol;
_solutionContainer.TryTransferSolution(ent, injectable, buffer, maxInject);
//Spawn Effect
var uidXform = Transform(ent);
Spawn(component.VisualEffectPrototype, uidXform.Coordinates);
}
}
}

}
Loading

0 comments on commit c279c6c

Please sign in to comment.