Skip to content

Commit

Permalink
Merge remote-tracking branch 'upstream/master' into 2024-12-16-contacts
Browse files Browse the repository at this point in the history
  • Loading branch information
metalgearsloth committed Jan 27, 2025
2 parents 95ec222 + e03aec4 commit bc57e39
Show file tree
Hide file tree
Showing 52 changed files with 836 additions and 381 deletions.
2 changes: 1 addition & 1 deletion Directory.Packages.props
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,7 @@
<PackageVersion Include="SpaceWizards.Sodium" Version="0.2.1" />
<PackageVersion Include="TerraFX.Interop.Windows" Version="10.0.26100.1" />
<PackageVersion Include="TerraFX.Interop.Xlib" Version="6.4.0" />
<PackageVersion Include="VorbisPizza" Version="1.4.2" />
<PackageVersion Include="VorbisPizza" Version="1.3.0" />
<PackageVersion Include="YamlDotNet" Version="16.3.0" />
<PackageVersion Include="prometheus-net" Version="8.2.1" />
<PackageVersion Include="prometheus-net.DotNetRuntime" Version="4.4.0" />
Expand Down
2 changes: 1 addition & 1 deletion MSBuild/Robust.Engine.Version.props
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
<Project>
<!-- This file automatically reset by Tools/version.py -->
<PropertyGroup><Version>239.0.0</Version></PropertyGroup>
<PropertyGroup><Version>240.1.2</Version></PropertyGroup>
</Project>
Expand Down
70 changes: 70 additions & 0 deletions RELEASE-NOTES.md
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,76 @@ END TEMPLATE-->
*None yet*


## 240.1.2


## 240.1.1

### Bugfixes

* Fixed one of the `IOverlayManager.RemoveOverlay` overrides not fully removing the overlay.


## 240.1.0

### New features

* Added an `AsNullable` extension method for converting an `Entity<T>` into an `Entity<T?>`

### Bugfixes

* Fixed an exception in `PhysicsSystem.DestroyContacts()` that could result in entities getting stuck with broken physics.

### Other

* `GamePrototypeLoadManager` will now send all uploaded prototypes to connecting players in a single `GamePrototypeLoadMessage`, as opposed to one message per upload.


## 240.0.1

### Bugfixes

* Fixed `SharedBroadphaseSystem.GetBroadphases()` not returning the map itself, which was causing physics to not work properly off-grid.


## 240.0.0

### Breaking changes

* `ComponentRegistry` no longer implements `ISerializationContext`
* Tickrate values are now `ushort`, allowing them to go up to 65535.

### New features

* Console completion options now have new flags for preventing suggestions from being escaped or quoted.
* Added `ILocalizationManager.HasCulture()`.
* Static `EntProtoId<T>` fields are now validated to exist.

### Bugfixes

* Fixed a state handling bug in replays, which was causing exceptions to be thrown when applying delta states.

### Other

* Reduced amount of `DynamicMethod`s used by serialization system. This should improve performance somewhat.

### Internal

* Avoided sorting overlays every render frame.
* Various clean up to grid fixture code/adding asserts.

## 239.0.1

### Bugfixes

* Fix logging of received packets with `net.packet` logging level.
* Downgrade `VorbisPizza` to fix audio playback for systems without AVX2 support.

### Other

* Improved performance of some Roslyn analyzers and source generators, which should significantly improve compile times and IDE performance.


## 239.0.0

### Breaking changes
Expand Down
114 changes: 114 additions & 0 deletions Robust.Analyzers.Tests/ByRefEventAnalyzerTest.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,114 @@
using System.Threading.Tasks;
using Microsoft.CodeAnalysis.CSharp.Testing;
using Microsoft.CodeAnalysis.Testing;
using NUnit.Framework;
using VerifyCS =
Microsoft.CodeAnalysis.CSharp.Testing.CSharpAnalyzerVerifier<Robust.Analyzers.ByRefEventAnalyzer, Microsoft.CodeAnalysis.Testing.DefaultVerifier>;

namespace Robust.Analyzers.Tests;

[Parallelizable(ParallelScope.All | ParallelScope.Fixtures)]
[TestFixture, TestOf(typeof(ByRefEventAnalyzer))]
public sealed class ByRefEventAnalyzerTest
{
private const string EventBusDef = """
namespace Robust.Shared.GameObjects;
public readonly struct EntityUid;
public sealed class EntitySystem
{
public void RaiseLocalEvent<TEvent>(EntityUid uid, ref TEvent args, bool broadcast = false)
where TEvent : notnull { }
public void RaiseLocalEvent<TEvent>(EntityUid uid, TEvent args, bool broadcast = false)
where TEvent : notnull { }
}
public sealed class EntityEventBus
{
public void RaiseLocalEvent<TEvent>(EntityUid uid, ref TEvent args, bool broadcast = false)
where TEvent : notnull { }
public void RaiseLocalEvent<TEvent>(EntityUid uid, TEvent args, bool broadcast = false)
where TEvent : notnull { }
}
""";

private static Task Verifier(string code, params DiagnosticResult[] expected)
{
var test = new CSharpAnalyzerTest<ByRefEventAnalyzer, DefaultVerifier>()
{
TestState =
{
Sources = { code }
},
};

TestHelper.AddEmbeddedSources(
test.TestState,
"Robust.Shared.GameObjects.EventBusAttributes.cs"
);

test.TestState.Sources.Add(("EntityEventBus.cs", EventBusDef));

// ExpectedDiagnostics cannot be set, so we need to AddRange here...
test.TestState.ExpectedDiagnostics.AddRange(expected);

return test.RunAsync();
}

[Test]
public async Task TestSuccess()
{
const string code = """
using Robust.Shared.GameObjects;
[ByRefEvent]
public readonly struct RefEvent;
public readonly struct ValueEvent;
public static class Foo
{
public static void Bar(EntityEventBus bus)
{
bus.RaiseLocalEvent(default(EntityUid), new ValueEvent());
var refEv = new RefEvent();
bus.RaiseLocalEvent(default(EntityUid), ref refEv);
}
}
""";

await Verifier(code);
}

[Test]
public async Task TestWrong()
{
const string code = """
using Robust.Shared.GameObjects;
[ByRefEvent]
public readonly struct RefEvent;
public readonly struct ValueEvent;
public static class Foo
{
public static void Bar(EntityEventBus bus)
{
bus.RaiseLocalEvent(default(EntityUid), new RefEvent());
var valueEv = new ValueEvent();
bus.RaiseLocalEvent(default(EntityUid), ref valueEv);
}
}
""";

await Verifier(
code,
// /0/Test0.cs(11,49): error RA0015: Tried to raise a by-ref event 'RefEvent' by value
VerifyCS.Diagnostic(ByRefEventAnalyzer.ByRefEventRaisedByValueRule).WithSpan(11, 49, 11, 63).WithArguments("RefEvent"),
// /0/Test0.cs(13,49): error RA0016: Tried to raise a value event 'ValueEvent' by-ref
VerifyCS.Diagnostic(ByRefEventAnalyzer.ByValueEventRaisedByRefRule).WithSpan(13, 49, 13, 60).WithArguments("ValueEvent")
);
}
}
4 changes: 4 additions & 0 deletions Robust.Analyzers.Tests/ComponentPauseGeneratorTest.cs
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,7 @@ public sealed partial class FooComponent : IComponent
public partial class FooComponent
{
[RobustAutoGenerated]
[global::System.ComponentModel.EditorBrowsable(global::System.ComponentModel.EditorBrowsableState.Never)]
public sealed class FooComponent_AutoPauseSystem : EntitySystem
{
public override void Initialize()
Expand Down Expand Up @@ -106,6 +107,7 @@ public sealed partial class FooComponent : IComponent
public partial class FooComponent
{
[RobustAutoGenerated]
[global::System.ComponentModel.EditorBrowsable(global::System.ComponentModel.EditorBrowsableState.Never)]
public sealed class FooComponent_AutoPauseSystem : EntitySystem
{
public override void Initialize()
Expand Down Expand Up @@ -147,6 +149,7 @@ public sealed partial class FooComponent : IComponent
public partial class FooComponent
{
[RobustAutoGenerated]
[global::System.ComponentModel.EditorBrowsable(global::System.ComponentModel.EditorBrowsableState.Never)]
public sealed class FooComponent_AutoPauseSystem : EntitySystem
{
public override void Initialize()
Expand Down Expand Up @@ -188,6 +191,7 @@ public sealed partial class FooComponent : IComponent
public partial class FooComponent
{
[RobustAutoGenerated]
[global::System.ComponentModel.EditorBrowsable(global::System.ComponentModel.EditorBrowsableState.Never)]
public sealed class FooComponent_AutoPauseSystem : EntitySystem
{
public override void Initialize()
Expand Down
1 change: 1 addition & 0 deletions Robust.Analyzers.Tests/Robust.Analyzers.Tests.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
<EmbeddedResource Include="..\Robust.Shared\Analyzers\PreferNonGenericVariantForAttribute.cs" LogicalName="Robust.Shared.Analyzers.PreferNonGenericVariantForAttribute.cs" LinkBase="Implementations" />
<EmbeddedResource Include="..\Robust.Shared\Analyzers\PreferOtherTypeAttribute.cs" LogicalName="Robust.Shared.Analyzers.PreferOtherTypeAttribute.cs" LinkBase="Implementations" />
<EmbeddedResource Include="..\Robust.Shared\IoC\DependencyAttribute.cs" LogicalName="Robust.Shared.IoC.DependencyAttribute.cs" LinkBase="Implementations" />
<EmbeddedResource Include="..\Robust.Shared\GameObjects\EventBusAttributes.cs" LogicalName="Robust.Shared.GameObjects.EventBusAttributes.cs" LinkBase="Implementations" />
</ItemGroup>

<PropertyGroup>
Expand Down
54 changes: 33 additions & 21 deletions Robust.Analyzers/ByRefEventAnalyzer.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
#nullable enable
#nullable enable
using System.Collections.Immutable;
using System.Linq;
using Microsoft.CodeAnalysis;
Expand All @@ -24,7 +24,7 @@ public sealed class ByRefEventAnalyzer : DiagnosticAnalyzer
"Make sure that methods subscribing to a ref event have the ref keyword for the event argument."
);

private static readonly DiagnosticDescriptor ByRefEventRaisedByValueRule = new(
public static readonly DiagnosticDescriptor ByRefEventRaisedByValueRule = new(
Diagnostics.IdByRefEventRaisedByValue,
"By-ref event raised by value",
"Tried to raise a by-ref event '{0}' by value",
Expand All @@ -34,7 +34,7 @@ public sealed class ByRefEventAnalyzer : DiagnosticAnalyzer
"Make sure to use the ref keyword when raising ref events."
);

private static readonly DiagnosticDescriptor ByValueEventRaisedByRefRule = new(
public static readonly DiagnosticDescriptor ByValueEventRaisedByRefRule = new(
Diagnostics.IdValueEventRaisedByRef,
"Value event raised by-ref",
"Tried to raise a value event '{0}' by-ref",
Expand All @@ -54,32 +54,44 @@ public override void Initialize(AnalysisContext context)
{
context.ConfigureGeneratedCodeAnalysis(GeneratedCodeAnalysisFlags.Analyze | GeneratedCodeAnalysisFlags.ReportDiagnostics);
context.EnableConcurrentExecution();
context.RegisterOperationAction(CheckEventRaise, OperationKind.Invocation);
context.RegisterCompilationStartAction(compilationContext =>
{
var raiseMethods = compilationContext.Compilation
.GetTypeByMetadataName("Robust.Shared.GameObjects.EntitySystem")?
.GetMembers()
.Where(m => m.Name.Contains("RaiseLocalEvent") && m.Kind == SymbolKind.Method)
.Cast<IMethodSymbol>();

var busRaiseMethods = compilationContext.Compilation
.GetTypeByMetadataName("Robust.Shared.GameObjects.EntityEventBus")?
.GetMembers()
.Where(m => m.Name.Contains("RaiseLocalEvent") && m.Kind == SymbolKind.Method)
.Cast<IMethodSymbol>();

if (raiseMethods == null)
return;

if (busRaiseMethods != null)
raiseMethods = raiseMethods.Concat(busRaiseMethods);

var raiseMethodsArray = raiseMethods.ToArray();

compilationContext.RegisterOperationAction(
ctx => CheckEventRaise(ctx, raiseMethodsArray),
OperationKind.Invocation);
});
}

private void CheckEventRaise(OperationAnalysisContext context)
private static void CheckEventRaise(
OperationAnalysisContext context,
IReadOnlyCollection<IMethodSymbol> raiseMethods)
{
if (context.Operation is not IInvocationOperation operation)
return;

var raiseMethods = context.Compilation
.GetTypeByMetadataName("Robust.Shared.GameObjects.EntitySystem")?
.GetMembers()
.Where(m => m.Name.Contains("RaiseLocalEvent") && m.Kind == SymbolKind.Method)
.Cast<IMethodSymbol>();

var busRaiseMethods = context.Compilation
.GetTypeByMetadataName("Robust.Shared.GameObjects.EntityEventBus")?
.GetMembers()
.Where(m => m.Name.Contains("RaiseLocalEvent") && m.Kind == SymbolKind.Method)
.Cast<IMethodSymbol>();

if (raiseMethods == null)
if (!operation.TargetMethod.Name.Contains("RaiseLocalEvent"))
return;

if (busRaiseMethods != null)
raiseMethods = raiseMethods.Concat(busRaiseMethods);

if (!raiseMethods.Any(m => m.Equals(operation.TargetMethod.OriginalDefinition, Default)))
{
// If you try to do this normally by concatenating like busRaiseMethods above
Expand Down
6 changes: 3 additions & 3 deletions Robust.Client/BaseClient.cs
Original file line number Diff line number Diff line change
Expand Up @@ -88,10 +88,10 @@ private void TickRateChanged(int tickrate, in CVarChangeInfo info)
{
if (GameInfo != null)
{
GameInfo.TickRate = (byte) tickrate;
GameInfo.TickRate = (ushort) tickrate;
}

_timing.SetTickRateAt((byte) tickrate, info.TickChanged);
_timing.SetTickRateAt((ushort) tickrate, info.TickChanged);
_logger.Info($"Tickrate changed to: {tickrate} on tick {_timing.CurTick}");
}

Expand Down Expand Up @@ -395,6 +395,6 @@ public ServerInfo(string serverName)
/// </summary>
public int ServerMaxPlayers { get; set; }

public byte TickRate { get; internal set; }
public uint TickRate { get; internal set; }
}
}
2 changes: 2 additions & 0 deletions Robust.Client/GameObjects/EntitySystems/AppearanceSystem.cs
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,8 @@ public override void Initialize()

protected override void OnAppearanceGetState(EntityUid uid, AppearanceComponent component, ref ComponentGetState args)
{
// TODO Game State
// Force the client to serialize & de-serialize implicitly generated component states.
var clone = CloneAppearanceData(component.AppearanceData);
args.State = new AppearanceComponentState(clone);
}
Expand Down
4 changes: 2 additions & 2 deletions Robust.Client/GameStates/ClientGameStateManager.cs
Original file line number Diff line number Diff line change
Expand Up @@ -399,7 +399,7 @@ public void ApplyGameState()

using (_prof.Group("MergeImplicitData"))
{
MergeImplicitData(createdEntities);
GenerateImplicitStates(createdEntities);
}

if (_lastProcessedInput < curState.LastProcessedInput)
Expand Down Expand Up @@ -671,7 +671,7 @@ public void ResetPredictedEntities()
/// initial server state for any newly created entity. It does this by simply using the standard <see
/// cref="IEntityManager.GetComponentState"/>.
/// </remarks>
private void MergeImplicitData(IEnumerable<NetEntity> createdEntities)
public void GenerateImplicitStates(IEnumerable<NetEntity> createdEntities)
{
var bus = _entityManager.EventBus;

Expand Down
6 changes: 6 additions & 0 deletions Robust.Client/GameStates/IClientGameStateManager.cs
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,12 @@ public interface IClientGameStateManager
/// </summary>
IEnumerable<NetEntity> ApplyGameState(GameState curState, GameState? nextState);

/// <summary>
/// Generates implicit component states for newly created entities.
/// This should always be called after running <see cref="ApplyGameState(GameState, GameState)"/>.
/// </summary>
void GenerateImplicitStates(IEnumerable<NetEntity> states);

/// <summary>
/// Resets any entities that have changed while predicting future ticks.
/// </summary>
Expand Down
Loading

0 comments on commit bc57e39

Please sign in to comment.