Skip to content

Commit

Permalink
Merge remote-tracking branch 'upstream/master' into upstream-sync
Browse files Browse the repository at this point in the history
# Conflicts:
#	Content.Server/Chat/Systems/ChatSystem.cs
#	LICENSE.TXT
#	Resources/Prototypes/Catalog/Fills/Lockers/heads.yml
#	Resources/Prototypes/Catalog/Fills/Lockers/security.yml
#	Resources/Prototypes/Entities/Mobs/Species/reptilian.yml
#	Resources/Textures/Clothing/Head/Hardsuits/rd.rsi/icon-flash.png
#	Resources/Textures/Clothing/Head/Hardsuits/rd.rsi/icon.png
#	Resources/Textures/Clothing/Head/Hardsuits/rd.rsi/meta.json
#	Resources/Textures/Clothing/Head/Hardsuits/rd.rsi/off-equipped-HELMET.png
#	Resources/Textures/Clothing/Head/Hardsuits/rd.rsi/off-inhand-left.png
#	Resources/Textures/Clothing/Head/Hardsuits/rd.rsi/off-inhand-right.png
#	Resources/Textures/Clothing/Head/Hardsuits/rd.rsi/on-equipped-HELMET.png
#	Resources/Textures/Clothing/Head/Hardsuits/rd.rsi/on-inhand-left.png
#	Resources/Textures/Clothing/Head/Hardsuits/rd.rsi/on-inhand-right.png
#	Resources/Textures/Clothing/Head/Hats/hoshat.rsi/equipped-HELMET-hamster.png
#	Resources/Textures/Clothing/Head/Hats/hoshat.rsi/equipped-HELMET.png
#	Resources/Textures/Clothing/Head/Hats/hoshat.rsi/icon.png
#	Resources/Textures/Clothing/Head/Hats/hoshat.rsi/inhand-left.png
#	Resources/Textures/Clothing/Head/Hats/hoshat.rsi/inhand-right.png
#	Resources/Textures/Clothing/Neck/Cloaks/hos.rsi/equipped-NECK.png
#	Resources/Textures/Clothing/Neck/Cloaks/hos.rsi/icon.png
#	Resources/Textures/Clothing/OuterClothing/Coats/hos_trenchcoat.rsi/equipped-OUTERCLOTHING.png
#	Resources/Textures/Clothing/OuterClothing/Coats/hos_trenchcoat.rsi/icon.png
#	Resources/Textures/Clothing/OuterClothing/Coats/hos_trenchcoat.rsi/inhand-left.png
#	Resources/Textures/Clothing/OuterClothing/Coats/hos_trenchcoat.rsi/inhand-right.png
#	Resources/Textures/Clothing/OuterClothing/Coats/hos_trenchcoat.rsi/meta.json
#	Resources/Textures/Clothing/OuterClothing/Hardsuits/rd.rsi/equipped-OUTERCLOTHING.png
#	Resources/Textures/Clothing/OuterClothing/Hardsuits/rd.rsi/icon.png
#	Resources/Textures/Clothing/OuterClothing/Hardsuits/rd.rsi/meta.json
#	Resources/Textures/Clothing/Uniforms/Jumpsuit/roboticist.rsi/meta.json
#	Resources/Textures/Structures/Piping/disposal.rsi/conmailing.png
#	Resources/Textures/Structures/Piping/disposal.rsi/mailing-charging.png
#	Resources/Textures/Structures/Piping/disposal.rsi/mailing-flush.png
#	Resources/Textures/Structures/Piping/disposal.rsi/mailing.png
#	Resources/Textures/Structures/Piping/disposal.rsi/mailover-handle.png
#	Resources/Textures/Structures/Piping/disposal.rsi/meta.json
  • Loading branch information
Morb0 committed Jan 2, 2024
2 parents 7f43383 + 897e1d3 commit f062cbc
Show file tree
Hide file tree
Showing 405 changed files with 418,278 additions and 409,249 deletions.
201 changes: 200 additions & 1 deletion Content.Client/Chemistry/EntitySystems/ChemistryGuideDataSystem.cs
Original file line number Diff line number Diff line change
@@ -1,16 +1,42 @@
using Content.Shared.Chemistry;
using System.Linq;
using Content.Client.Chemistry.Containers.EntitySystems;
using Content.Shared.Atmos.Prototypes;
using Content.Shared.Body.Part;
using Content.Shared.Chemistry;
using Content.Shared.Chemistry.Components;
using Content.Shared.Chemistry.Components.SolutionManager;
using Content.Shared.Chemistry.Reaction;
using Content.Shared.Chemistry.Reagent;
using Content.Shared.Kitchen.Components;
using Content.Shared.Prototypes;
using Robust.Shared.Prototypes;

namespace Content.Client.Chemistry.EntitySystems;

/// <inheritdoc/>
public sealed class ChemistryGuideDataSystem : SharedChemistryGuideDataSystem
{
[Dependency] private readonly SolutionContainerSystem _solutionContainer = default!;

[ValidatePrototypeId<MixingCategoryPrototype>]
private const string DefaultMixingCategory = "DummyMix";
[ValidatePrototypeId<MixingCategoryPrototype>]
private const string DefaultGrindCategory = "DummyGrind";
[ValidatePrototypeId<MixingCategoryPrototype>]
private const string DefaultJuiceCategory = "DummyJuice";
[ValidatePrototypeId<MixingCategoryPrototype>]
private const string DefaultCondenseCategory = "DummyCondense";

private readonly Dictionary<string, List<ReagentSourceData>> _reagentSources = new();

/// <inheritdoc/>
public override void Initialize()
{
base.Initialize();

SubscribeNetworkEvent<ReagentGuideRegistryChangedEvent>(OnReceiveRegistryUpdate);
SubscribeLocalEvent<PrototypesReloadedEventArgs>(OnPrototypesReloaded);
OnPrototypesReloaded(null);
}

private void OnReceiveRegistryUpdate(ReagentGuideRegistryChangedEvent message)
Expand All @@ -26,4 +52,177 @@ private void OnReceiveRegistryUpdate(ReagentGuideRegistryChangedEvent message)
Registry[key] = val;
}
}

private void OnPrototypesReloaded(PrototypesReloadedEventArgs? ev)
{
// this doesn't check what prototypes are being reloaded because, to be frank, we use a lot of them.
_reagentSources.Clear();
foreach (var reagent in PrototypeManager.EnumeratePrototypes<ReagentPrototype>())
{
_reagentSources.Add(reagent.ID, new());
}

foreach (var reaction in PrototypeManager.EnumeratePrototypes<ReactionPrototype>())
{
if (!reaction.Source)
continue;

var data = new ReagentReactionSourceData(
reaction.MixingCategories ?? new () { DefaultMixingCategory },
reaction);
foreach (var product in reaction.Products.Keys)
{
_reagentSources[product].Add(data);
}
}

foreach (var gas in PrototypeManager.EnumeratePrototypes<GasPrototype>())
{
if (gas.Reagent == null)
continue;

var data = new ReagentGasSourceData(
new () { DefaultCondenseCategory },
gas);
_reagentSources[gas.Reagent].Add(data);
}

// store the names of the entities used so we don't get repeats in the guide.
var usedNames = new List<string>();
foreach (var entProto in PrototypeManager.EnumeratePrototypes<EntityPrototype>())
{
if (entProto.Abstract || usedNames.Contains(entProto.Name))
continue;

if (!entProto.TryGetComponent<ExtractableComponent>(out var extractableComponent))
continue;

//these bloat the hell out of blood/fat
if (entProto.HasComponent<BodyPartComponent>())
continue;

//these feel obvious...
if (entProto.HasComponent<PillComponent>())
continue;

if (extractableComponent.JuiceSolution is { } juiceSolution)
{
var data = new ReagentEntitySourceData(
new() { DefaultJuiceCategory },
entProto,
juiceSolution);
foreach (var (id, _) in juiceSolution.Contents)
{
_reagentSources[id.Prototype].Add(data);
}

usedNames.Add(entProto.Name);
}


if (extractableComponent.GrindableSolution is { } grindableSolutionId &&
entProto.TryGetComponent<SolutionContainerManagerComponent>(out var manager) &&
_solutionContainer.TryGetSolution(manager, grindableSolutionId, out var grindableSolution))
{
var data = new ReagentEntitySourceData(
new() { DefaultGrindCategory },
entProto,
grindableSolution);
foreach (var (id, _) in grindableSolution.Contents)
{
_reagentSources[id.Prototype].Add(data);
}
usedNames.Add(entProto.Name);
}
}
}

public List<ReagentSourceData> GetReagentSources(string id)
{
return _reagentSources.GetValueOrDefault(id) ?? new List<ReagentSourceData>();
}
}

/// <summary>
/// A generic class meant to hold information about a reagent source.
/// </summary>
public abstract class ReagentSourceData
{
/// <summary>
/// The mixing type that applies to this source.
/// </summary>
public readonly IReadOnlyList<ProtoId<MixingCategoryPrototype>> MixingType;

/// <summary>
/// The number of distinct outputs. Used for primary ordering.
/// </summary>
public abstract int OutputCount { get; }

/// <summary>
/// A text string corresponding to this source. Typically a name. Used for secondary ordering.
/// </summary>
public abstract string IdentifierString { get; }

protected ReagentSourceData(List<ProtoId<MixingCategoryPrototype>> mixingType)
{
MixingType = mixingType;
}
}

/// <summary>
/// Used to store a reagent source that's an entity with a corresponding solution.
/// </summary>
public sealed class ReagentEntitySourceData : ReagentSourceData
{
public readonly EntityPrototype SourceEntProto;

public readonly Solution Solution;

public override int OutputCount => Solution.Contents.Count;

public override string IdentifierString => SourceEntProto.Name;

public ReagentEntitySourceData(List<ProtoId<MixingCategoryPrototype>> mixingType, EntityPrototype sourceEntProto, Solution solution)
: base(mixingType)
{
SourceEntProto = sourceEntProto;
Solution = solution;
}
}

/// <summary>
/// Used to store a reagent source that comes from a reaction between multiple reagents.
/// </summary>
public sealed class ReagentReactionSourceData : ReagentSourceData
{
public readonly ReactionPrototype ReactionPrototype;

public override int OutputCount => ReactionPrototype.Products.Count + ReactionPrototype.Reactants.Count(r => r.Value.Catalyst);

public override string IdentifierString => ReactionPrototype.ID;

public ReagentReactionSourceData(List<ProtoId<MixingCategoryPrototype>> mixingType, ReactionPrototype reactionPrototype)
: base(mixingType)
{
ReactionPrototype = reactionPrototype;
}
}

/// <summary>
/// Used to store a reagent source that comes from gas condensation.
/// </summary>
public sealed class ReagentGasSourceData : ReagentSourceData
{
public readonly GasPrototype GasPrototype;

public override int OutputCount => 1;

public override string IdentifierString => Loc.GetString(GasPrototype.Name);

public ReagentGasSourceData(List<ProtoId<MixingCategoryPrototype>> mixingType, GasPrototype gasPrototype)
: base(mixingType)
{
GasPrototype = gasPrototype;
}
}

77 changes: 41 additions & 36 deletions Content.Client/Decals/Overlays/DecalOverlay.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2,18 +2,17 @@
using Robust.Client.GameObjects;
using Robust.Client.Graphics;
using Robust.Shared.Enums;
using Robust.Shared.Map;
using Robust.Shared.Prototypes;

namespace Content.Client.Decals.Overlays
{
public sealed class DecalOverlay : Overlay
public sealed class DecalOverlay : GridOverlay
{
private readonly SpriteSystem _sprites;
private readonly IEntityManager _entManager;
private readonly IPrototypeManager _prototypeManager;

public override OverlaySpace Space => OverlaySpace.WorldSpaceBelowEntities;

private readonly Dictionary<string, (Texture Texture, bool SnapCardinals)> _cachedTextures = new(64);

public DecalOverlay(
Expand All @@ -28,52 +27,58 @@ public DecalOverlay(

protected override void Draw(in OverlayDrawArgs args)
{
if (args.MapId == MapId.Nullspace)
return;

var grid = Grid;

if (!_entManager.TryGetComponent(grid, out DecalGridComponent? decalGrid) ||
!_entManager.TryGetComponent(grid, out TransformComponent? xform))
{
return;
}

if (xform.MapID != args.MapId)
return;

// Shouldn't need to clear cached textures unless the prototypes get reloaded.
var handle = args.WorldHandle;
var xformSystem = _entManager.System<TransformSystem>();
var eyeAngle = args.Viewport.Eye?.Rotation ?? Angle.Zero;

var gridQuery = _entManager.AllEntityQueryEnumerator<DecalGridComponent, TransformComponent>();
var zIndexDictionary = decalGrid.DecalRenderIndex;

while (gridQuery.MoveNext(out var decalGrid, out var xform))
{
if (xform.MapID != args.MapId)
continue;
if (zIndexDictionary.Count == 0)
return;

var zIndexDictionary = decalGrid.DecalRenderIndex;
var (_, worldRot, worldMatrix) = xformSystem.GetWorldPositionRotationMatrix(xform);

if (zIndexDictionary.Count == 0)
continue;
handle.SetTransform(worldMatrix);

var (_, worldRot, worldMatrix) = xformSystem.GetWorldPositionRotationMatrix(xform);
foreach (var decals in zIndexDictionary.Values)
{
foreach (var decal in decals.Values)
{
if (!_cachedTextures.TryGetValue(decal.Id, out var cache) && _prototypeManager.TryIndex<DecalPrototype>(decal.Id, out var decalProto))
{
cache = (_sprites.Frame0(decalProto.Sprite), decalProto.SnapCardinals);
_cachedTextures[decal.Id] = cache;
}

handle.SetTransform(worldMatrix);
var cardinal = Angle.Zero;

foreach (var decals in zIndexDictionary.Values)
{
foreach (var decal in decals.Values)
if (cache.SnapCardinals)
{
if (!_cachedTextures.TryGetValue(decal.Id, out var cache) && _prototypeManager.TryIndex<DecalPrototype>(decal.Id, out var decalProto))
{
cache = (_sprites.Frame0(decalProto.Sprite), decalProto.SnapCardinals);
_cachedTextures[decal.Id] = cache;
}

var cardinal = Angle.Zero;

if (cache.SnapCardinals)
{
var worldAngle = eyeAngle + worldRot;
cardinal = worldAngle.GetCardinalDir().ToAngle();
}

var angle = decal.Angle - cardinal;

if (angle.Equals(Angle.Zero))
handle.DrawTexture(cache.Texture, decal.Coordinates, decal.Color);
else
handle.DrawTexture(cache.Texture, decal.Coordinates, angle, decal.Color);
var worldAngle = eyeAngle + worldRot;
cardinal = worldAngle.GetCardinalDir().ToAngle();
}

var angle = decal.Angle - cardinal;

if (angle.Equals(Angle.Zero))
handle.DrawTexture(cache.Texture, decal.Coordinates, decal.Color);
else
handle.DrawTexture(cache.Texture, decal.Coordinates, angle, decal.Color);
}
}

Expand Down
9 changes: 6 additions & 3 deletions Content.Client/Doors/AirlockSystem.cs
Original file line number Diff line number Diff line change
Expand Up @@ -95,14 +95,16 @@ private void OnAppearanceChange(EntityUid uid, AirlockComponent comp, ref Appear
if (_appearanceSystem.TryGetData<bool>(uid, DoorVisuals.Powered, out var powered, args.Component) && powered)
{
boltedVisible = _appearanceSystem.TryGetData<bool>(uid, DoorVisuals.BoltLights, out var lights, args.Component)
&& lights && state == DoorState.Closed;
&& lights && (state == DoorState.Closed || state == DoorState.Open || state == DoorState.Welded);

emergencyLightsVisible = _appearanceSystem.TryGetData<bool>(uid, DoorVisuals.EmergencyLights, out var eaLights, args.Component) && eaLights;
unlitVisible =
state == DoorState.Closing
(state == DoorState.Closing
|| state == DoorState.Opening
|| state == DoorState.Denying
|| (state == DoorState.Open && comp.OpenUnlitVisible)
|| (_appearanceSystem.TryGetData<bool>(uid, DoorVisuals.ClosedLights, out var closedLights, args.Component) && closedLights);
|| (_appearanceSystem.TryGetData<bool>(uid, DoorVisuals.ClosedLights, out var closedLights, args.Component) && closedLights))
&& !boltedVisible && !emergencyLightsVisible; ;
}

args.Sprite.LayerSetVisible(DoorVisualLayers.BaseUnlit, unlitVisible);
Expand All @@ -115,6 +117,7 @@ private void OnAppearanceChange(EntityUid uid, AirlockComponent comp, ref Appear
&& state != DoorState.Open
&& state != DoorState.Opening
&& state != DoorState.Closing
&& !boltedVisible
);
}
}
Expand Down
3 changes: 1 addition & 2 deletions Content.Client/Explosion/ExplosionOverlaySystem.cs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@
using Robust.Shared.Graphics.RSI;
using Robust.Shared.Map;
using Robust.Shared.Prototypes;
using Robust.Shared.Utility;

namespace Content.Client.Explosion;

Expand Down Expand Up @@ -53,7 +52,7 @@ private void OnExplosionHandleState(EntityUid uid, ExplosionVisualsComponent com

private void OnCompRemove(EntityUid uid, ExplosionVisualsComponent component, ComponentRemove args)
{
if (TryComp(uid, out ExplosionVisualsTexturesComponent? textures))
if (TryComp(uid, out ExplosionVisualsTexturesComponent? textures) && !Deleted(textures.LightEntity))
QueueDel(textures.LightEntity);
}

Expand Down
Loading

0 comments on commit f062cbc

Please sign in to comment.