Skip to content
Open
Show file tree
Hide file tree
Changes from all 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
2 changes: 1 addition & 1 deletion EXILED/Exiled.API/Features/Room.cs
Original file line number Diff line number Diff line change
Expand Up @@ -500,7 +500,7 @@ private static RoomType FindType(GameObject gameObject)
"HCZ_Corner_Deep" => RoomType.HczCornerDeep,
"HCZ_Straight" => RoomType.HczStraight,
"HCZ_Straight_C" => RoomType.HczStraightC,
"HCZ_Straight_PipeRoom"=> RoomType.HczStraightPipeRoom,
"HCZ_Straight_PipeRoom" => RoomType.HczStraightPipeRoom,
"HCZ_Straight Variant" => RoomType.HczStraightVariant,
"HCZ_ChkpA" => RoomType.HczElevatorA,
"HCZ_ChkpB" => RoomType.HczElevatorB,
Expand Down
26 changes: 3 additions & 23 deletions EXILED/Exiled.API/Structs/AttachmentIdentifier.cs
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ namespace Exiled.API.Structs
using System.Linq;

using Exiled.API.Enums;

using Exiled.API.Features.Items;
using InventorySystem.Items.Firearms.Attachments;
using InventorySystem.Items.Firearms.Attachments.Components;

Expand Down Expand Up @@ -129,41 +129,21 @@ internal AttachmentIdentifier(uint code, AttachmentName name, AttachmentSlot slo
/// <returns>A <see cref="uint"/> value representing the subtraction between the two operands.</returns>
public static uint operator -(uint left, AttachmentIdentifier right) => left - right.Code;

/// <summary>
/// Converts the string representation of a <see cref="AttachmentIdentifier"/> to its <see cref="AttachmentIdentifier"/> equivalent.
/// A return value indicates whether the conversion is succeeded or failed.
/// </summary>
/// <param name="s">The <see cref="string"/> to convert.</param>
/// <param name="identifier">The converted <see cref="string"/>.</param>
/// <returns><see langword="true"/> if <see cref="string"/> was converted successfully; otherwise, <see langword="false"/>.</returns>
public static bool TryParse(string s, out AttachmentIdentifier identifier)
{
identifier = default;

foreach (AttachmentIdentifier attId in Features.Items.Firearm.AvailableAttachments.Values.SelectMany(kvp => kvp.Where(kvp2 => kvp2.Name.ToString() == s)))
{
identifier = attId;
return true;
}

return false;
}

Comment on lines -132 to -151
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is a breaking change. Either keep this method here or change the target branch to Dev (which will only be released when Exiled 10 comes out)

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The existence of this method itself is a critical bug, not the fact that I removed it in this PR. https://discord.com/channels/656673194693885975/1002713309876854924/1488609613258559681 There's not a single reference to this method in the code. It also seems unlikely that anyone has ever used it. Do you really want to keep this bug around until the next version of the game is released?

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sorry for taking so long to respond to this. But to answer your question, yes I do want to keep this even if it's buggy as some other plugin could have used this method and then that entire plugin would throw a MissingMethodException whenever it tries to call this

/// <summary>
/// Gets a <see cref="AttachmentIdentifier"/> by name.
/// </summary>
/// <param name="type">Weapons <see cref="FirearmType"/>.</param>
/// <param name="name">Attachment name.</param>
/// <returns><see cref="AttachmentIdentifier"/> instance.</returns>
public static AttachmentIdentifier Get(FirearmType type, AttachmentName name) => Features.Items.Firearm.AvailableAttachments[type].FirstOrDefault(identifier => identifier.Name == name);
public static AttachmentIdentifier Get(FirearmType type, AttachmentName name) => Firearm.AvailableAttachments[type].FirstOrDefault(identifier => identifier.Name == name);

/// <summary>
/// Gets the all <see cref="AttachmentIdentifier"/>'s for type, by slot.
/// </summary>
/// <param name="type">Weapons <see cref="FirearmType"/>.</param>
/// <param name="slot">Attachment slot.</param>
/// <returns><see cref="AttachmentIdentifier"/> instance.</returns>
public static IEnumerable<AttachmentIdentifier> Get(FirearmType type, AttachmentSlot slot) => Features.Items.Firearm.AvailableAttachments[type].Where(identifier => identifier.Slot == slot);
public static IEnumerable<AttachmentIdentifier> Get(FirearmType type, AttachmentSlot slot) => Firearm.AvailableAttachments[type].Where(identifier => identifier.Slot == slot);

/// <summary>
/// Converts the string representation of a <see cref="AttachmentName"/> to its <see cref="AttachmentName"/> equivalent.
Expand Down
3 changes: 2 additions & 1 deletion EXILED/Exiled.CustomRoles/CustomRoles.cs
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,8 @@ public CustomRoles()
Loader.Deserializer = new DeserializerBuilder()
.WithTypeConverter(new VectorsConverter())
.WithTypeConverter(new ColorConverter())
.WithTypeConverter(new AttachmentIdentifiersConverter())
.WithTypeConverter(new AttachmentNameConverter())
.WithTypeConverter(new AttachmentIdentifierConverter())
.WithNamingConvention(UnderscoredNamingConvention.Instance)
.WithNodeDeserializer(inner => new AbstractClassNodeTypeResolver(inner, new AggregateExpectationTypeResolver<CustomAbility>(UnderscoredNamingConvention.Instance)), s => s.InsteadOf<ObjectNodeDeserializer>())
.IgnoreFields()
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
// -----------------------------------------------------------------------
// <copyright file="AttachmentIdentifierConverter.cs" company="ExMod Team">
// Copyright (c) ExMod Team. All rights reserved.
// Licensed under the CC BY-SA 3.0 license.
// </copyright>
// -----------------------------------------------------------------------

namespace Exiled.Loader.Features.Configs.CustomConverters
{
using System;
using System.Linq;

using API.Structs;

using Exiled.API.Enums;
using Exiled.API.Features.Items;

using InventorySystem.Items.Firearms.Attachments;

using YamlDotNet.Core;
using YamlDotNet.Core.Events;
using YamlDotNet.Serialization;

/// <summary>
/// Converter <see cref="FirearmType"/> and <see cref="AttachmentName"/> to <see cref="AttachmentIdentifier"/>.
/// </summary>
public sealed class AttachmentIdentifierConverter : IYamlTypeConverter
{
/// <inheritdoc cref="IYamlTypeConverter" />
public bool Accepts(Type type) => type == typeof(AttachmentIdentifier);

/// <inheritdoc cref="IYamlTypeConverter" />
public object ReadYaml(IParser parser, Type type)
{
if (!parser.TryConsume(out Scalar scalar))
throw new InvalidOperationException($"Expected a scalar for {nameof(AttachmentIdentifier)}.");

string[] parts = scalar?.Value?.Split(':');
if (parts.Length != 3)
throw new InvalidOperationException($"Invalid AttachmentIdentifier format: '{scalar?.Value}'. Expected \"AttachmentName:AttachmentSlot:AttachmentCode\".");

if (!Enum.TryParse(parts[0], true, out AttachmentName attachmentName))
throw new InvalidOperationException($"Invalid AttachmentName: '{parts[0]}'.");

if (!Enum.TryParse(parts[1], true, out AttachmentSlot attachmentSlot))
throw new InvalidOperationException($"Invalid AttachmentSlot: '{parts[1]}'.");

if (!uint.TryParse(parts[2], out uint code))
throw new InvalidOperationException($"Invalid AttachmentCode: '{parts[2]}'.");

return Firearm.AvailableAttachments
.SelectMany(kvp => kvp.Value)
.FirstOrDefault(att => att.Name == attachmentName && att.Slot == attachmentSlot && att.Code == code);
}

/// <inheritdoc cref="IYamlTypeConverter" />
public void WriteYaml(IEmitter emitter, object value, Type type)
{
AttachmentIdentifier attId = default;

if (value is AttachmentIdentifier castAttId)
attId = castAttId;

// If anyone ever looks at this code and doesn't understand why it's implemented the way it is, here's an explanation. The problem is that the NW code doesn't provide a way to properly serialize attachments into a string so that this string can then be deserialized back into an object while maintaining integrity. Therefore, literally the only way to obtain an object is to store it as three properties. Storing only "AttachmentName" will cause problems. Storing it as "FirearmType:AttachmentName" will also cause problems.
// https://discord.com/channels/656673194693885975/1002713309876854924/1488655471697989682
emitter.Emit(new Scalar($"{attId.Name}:{attId.Slot}:{attId.Code}"));
}
}
}
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
// -----------------------------------------------------------------------
// <copyright file="AttachmentIdentifiersConverter.cs" company="ExMod Team">
// <copyright file="AttachmentNameConverter.cs" company="ExMod Team">
// Copyright (c) ExMod Team. All rights reserved.
// Licensed under the CC BY-SA 3.0 license.
// </copyright>
Expand All @@ -22,7 +22,7 @@ namespace Exiled.Loader.Features.Configs.CustomConverters
/// <summary>
/// Converts a <see cref="IEnumerable{T}"/> of <see cref="AttachmentName"/> to Yaml configs and vice versa.
/// </summary>
public sealed class AttachmentIdentifiersConverter : IYamlTypeConverter
public sealed class AttachmentNameConverter : IYamlTypeConverter
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is another breaking change. Albeit more minor

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This doesn't affect anything at all. Not only was the name incorrect, it also got in the way of developing a new feature.

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If any Exiled plugin whatsoever used this converter in their own code, after this change they'd get a TypeLoadException. So I'm not approving of this PR until it's either set to target Dev, or if these breaking changes are removed

{
/// <inheritdoc cref="IYamlTypeConverter" />
public bool Accepts(Type type) => type == typeof(AttachmentName);
Expand Down
6 changes: 4 additions & 2 deletions EXILED/Exiled.Loader/Loader.cs
Original file line number Diff line number Diff line change
Expand Up @@ -106,7 +106,8 @@ public Loader()
public static ISerializer Serializer { get; set; } = new SerializerBuilder()
.WithTypeConverter(new VectorsConverter())
.WithTypeConverter(new ColorConverter())
.WithTypeConverter(new AttachmentIdentifiersConverter())
.WithTypeConverter(new AttachmentNameConverter())
.WithTypeConverter(new AttachmentIdentifierConverter())
.WithEventEmitter(eventEmitter => new TypeAssigningEventEmitter(eventEmitter))
.WithTypeInspector(inner => new CommentGatheringTypeInspector(inner))
.WithEmissionPhaseObjectGraphVisitor(args => new CommentsObjectGraphVisitor(args.InnerVisitor))
Expand All @@ -121,7 +122,8 @@ public Loader()
public static IDeserializer Deserializer { get; set; } = new DeserializerBuilder()
.WithTypeConverter(new VectorsConverter())
.WithTypeConverter(new ColorConverter())
.WithTypeConverter(new AttachmentIdentifiersConverter())
.WithTypeConverter(new AttachmentNameConverter())
.WithTypeConverter(new AttachmentIdentifierConverter())
.WithNamingConvention(UnderscoredNamingConvention.Instance)
.WithNodeDeserializer(inner => new ValidatingNodeDeserializer(inner), deserializer => deserializer.InsteadOf<ObjectNodeDeserializer>())
.IgnoreFields()
Expand Down
Loading