Skip to content

Commit 7de6428

Browse files
Misaka-ZeroTwoJesus-QCVALERA771louis1706IRacle1
authored
v8.12.0-rc.1 (#52)
* uwu (#5) * AdminToy.List (#18) * AdminToy.List * Better AdminToy::Get() * Update EXILED/Exiled.API/Features/Toys/AdminToy.cs Co-authored-by: IRacle <79921583+IRacle1@users.noreply.github.com> * TODO * Fix Error * Fix2 --------- Co-authored-by: IRacle <79921583+IRacle1@users.noreply.github.com> * Fix `Jailbird::WearState` (#12) * Jailbird * Fix * Exception * Fix NW moment * Porting EXILED9 RespawnedTeam event. by.VALERA771 (#27) Exiled-Team/EXILED#2386 * Fix not returning null (#22) * Fix not returning null * Apply suggestions from code review Co-authored-by: Jesus QC <69375249+Jesus-QC@users.noreply.github.com> * Little modification --------- Co-authored-by: Jesus QC <69375249+Jesus-QC@users.noreply.github.com> * RecontainedEventArgs more feature (#20) * RecontainedEventArgs more feature * Fix Naming * grammar * Update RecontainedEventArgs.cs --------- Co-authored-by: Misaka-ZeroTwo <45165615+Misaka-ZeroTwo@users.noreply.github.com> * InteractingScp330.cs: Reduction of bloat code from original design. (#30) * Should reduce bloat code that was required years ago. * Should reduce bloat code that was required years ago. * Added back per Yamato's request --------- Co-authored-by: Yamato <66829532+louis1706@users.noreply.github.com> * IScp330Event (#11) Co-authored-by: Misaka-ZeroTwo <45165615+Misaka-ZeroTwo@users.noreply.github.com> * PR than i made (#9) * PR made by me Thanks Ika for the Help on CustomAmmo/CategoryLimit Co-Authored-By: Ika <36999341+IkaOverride@users.noreply.github.com> * Build error * Added support to SCPs for escaping-related events. * spacing * LocalReporting Exiled should be call before NWAPI * Optimising / More documentation on SpawningItem * ISpawnableScp * Use of ComponentsEqualityComparer for Dictionary --------- Co-authored-by: Ika <36999341+IkaOverride@users.noreply.github.com> * [Events] Fix null reference (#15) * fix situation when `ply == null` * lol why --------- Co-authored-by: IRacle <zornik2006@yandex.ru> * Offline mode support (#19) * Fix Offline-mode breaking everything * Add `offline` authentication type and append `@offline` to UserIds during offline mode * Add offline id support to Player.Get * Comment transpilers --------- Co-authored-by: Yamato <66829532+louis1706@users.noreply.github.com> * Fix NW bugs (#32) * Fix Armor Drop from https://git.scpslgame.com/northwood-qa/scpsl-bug-reporting/-/issues/230 * add comments * fix scp173 and adding bug report link to summary class fix https://git.scpslgame.com/northwood-qa/scpsl-bug-reporting/-/issues/143 * Moved patches and fixed Scp173FirstKillPatch * Add Slowness Fix Avoid values more than 100 for effect slowness to fix https://git.scpslgame.com/northwood-qa/scpsl-bug-reporting/-/issues/378 * skill issue * skill issue (again= --------- Co-authored-by: Yamato <66829532+louis1706@users.noreply.github.com> * Useless Event (939 Placed Amnestic Cloud) (#40) * Fix custom role classes giving custom ammo when they are not suppose to (#24) * Fix custom role classes giving custom ammmo when they are not suppose to * change to using EnumUtils * Moved Ammo additions into Inventory call delayed * `Item::<T>Get()` and `Pickup::<T>Get()` (#17) * `Item::::<T>Get()` and `Pickup::<T>Get()` * Revert doc change * Add `Hazard::Get<T>()` * doc fix * `Door::Get<T>()` * AdminToy.Get<T>() * More <T> implementation * WeirdFix * simplify Scp244Spawning patch and AddedComment & NO IL error * Remove Log.info * DroppingItem light modifiication * Moving Item.Get inside the eventargs instead of transpiller * FixNpcNoclip (#34) * FixNpcNoclip * oups * . * virtual / override * Implements more patches for RemovingHandcuffs event and adding RemovedHandcuffs event (#3) * Update labeler.yml * RemovingHandcuffs event * Update UncuffReason.cs * New event * docs * Interacting scp330 compile fix (#43) * My scp built with no issues.. no idea why. * Fixes issue * Harmony suppresses NON harmony errors. --------- Co-authored-by: Yamato <66829532+louis1706@users.noreply.github.com> * Trello is no more & more NW Fix & Fix IL Code on dev (#28) * Trello Is Replaced by gitlab * also this one * Fix106RegenerationWithScp244 * Report To NW * . * Scp3114FriendlyFireFix * Fix * yamatotototo * Fix * Fix for building dev + TODO than i just seen * Fix Undid patch * fIX * Fix Client Crash Issue --------- Co-authored-by: IRacle <zornik2006@yandex.ru> * Additions (#29) * Add a bunch * Fix * Security * Make changes * remove unused usings * Getting inventory * oops * Dev commit * use exiled --------- Co-authored-by: Yamato <66829532+louis1706@users.noreply.github.com> * `[EXILED::API]` Pickup::Category (#46) * Item Category on Pickup * Fixed Build Error * Fix (#50) --------- Co-authored-by: Jesus QC <69375249+Jesus-QC@users.noreply.github.com> Co-authored-by: VALERA771 <72030575+VALERA771@users.noreply.github.com> Co-authored-by: Yamato <66829532+louis1706@users.noreply.github.com> Co-authored-by: IRacle <79921583+IRacle1@users.noreply.github.com> Co-authored-by: 永安404 <101850798+YongAn404@users.noreply.github.com> Co-authored-by: X <24619207+Undid-Iridium@users.noreply.github.com> Co-authored-by: Ika <36999341+IkaOverride@users.noreply.github.com> Co-authored-by: IRacle <zornik2006@yandex.ru> Co-authored-by: x3rt <x3rtdev@gmail.com> Co-authored-by: sky <99112969+skyyt15@users.noreply.github.com> Co-authored-by: TtroubleTT <121741230+TtroubleTT@users.noreply.github.com> Co-authored-by: Nameless <85962933+Misfiy@users.noreply.github.com> Co-authored-by: ZeroTwo <63092138+NotZer0Two@users.noreply.github.com>
1 parent 8b8eb96 commit 7de6428

File tree

121 files changed

+2351
-407
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

121 files changed

+2351
-407
lines changed

EXILED/Exiled.API/Enums/AuthenticationType.cs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,5 +42,10 @@ public enum AuthenticationType
4242
/// Indicates that the player has been authenticated as DedicatedServer.
4343
/// </summary>
4444
DedicatedServer,
45+
46+
/// <summary>
47+
/// Indicates that the player has been authenticated during Offline mode.
48+
/// </summary>
49+
Offline,
4550
}
4651
}

EXILED/Exiled.API/Enums/HazardType.cs

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
// -----------------------------------------------------------------------
2+
// <copyright file="HazardType.cs" company="Exiled Team">
3+
// Copyright (c) Exiled Team. All rights reserved.
4+
// Licensed under the CC BY-SA 3.0 license.
5+
// </copyright>
6+
// -----------------------------------------------------------------------
7+
8+
namespace Exiled.API.Enums
9+
{
10+
using Exiled.API.Features.Hazards;
11+
12+
/// <summary>
13+
/// Unique identifier for a <see cref="Hazard"/>.
14+
/// </summary>
15+
public enum HazardType
16+
{
17+
/// <summary>
18+
/// SCP-939 amnestic cloud.
19+
/// </summary>
20+
AmnesticCloud,
21+
22+
/// <summary>
23+
/// Sinkhole spawned at start of round.
24+
/// </summary>
25+
Sinkhole,
26+
27+
/// <summary>
28+
/// SCP-173 tantrum.
29+
/// </summary>
30+
Tantrum,
31+
32+
/// <summary>
33+
/// Should never happen
34+
/// </summary>
35+
Unknown,
36+
}
37+
}
Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
// -----------------------------------------------------------------------
2+
// <copyright file="UncuffReason.cs" company="Exiled Team">
3+
// Copyright (c) Exiled Team. All rights reserved.
4+
// Licensed under the CC BY-SA 3.0 license.
5+
// </copyright>
6+
// -----------------------------------------------------------------------
7+
8+
namespace Exiled.API.Enums
9+
{
10+
/// <summary>
11+
/// Reasons that player gets uncuffed.
12+
/// </summary>
13+
public enum UncuffReason
14+
{
15+
/// <summary>
16+
/// Uncuffed by a player.
17+
/// </summary>
18+
Player,
19+
20+
/// <summary>
21+
/// Uncuffed due to the distance between cuffer and target.
22+
/// </summary>
23+
OutOfRange,
24+
25+
/// <summary>
26+
/// Uncuffed due to the cuffer no longer alive.
27+
/// </summary>
28+
CufferDied,
29+
}
30+
}
Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
1+
// -----------------------------------------------------------------------
2+
// <copyright file="BitwiseExtensions.cs" company="Exiled Team">
3+
// Copyright (c) Exiled Team. All rights reserved.
4+
// Licensed under the CC BY-SA 3.0 license.
5+
// </copyright>
6+
// -----------------------------------------------------------------------
7+
8+
namespace Exiled.API.Extensions
9+
{
10+
using System;
11+
12+
/// <summary>
13+
/// Extensions for bitwise operations.
14+
/// </summary>
15+
public static class BitwiseExtensions
16+
{
17+
/// <summary>
18+
/// Adds the specified flags to the given enum value.
19+
/// </summary>
20+
/// <typeparam name="T">The type of the enum.</typeparam>
21+
/// <param name="flags">The enum value to add flags to.</param>
22+
/// <param name="newFlags">The flags to add.</param>
23+
/// <returns>The enum value with the specified flags added.</returns>
24+
public static T AddFlags<T>(this T flags, params T[] newFlags)
25+
where T : Enum => flags.ModifyFlags(true, newFlags);
26+
27+
/// <summary>
28+
/// Removes the specified flags from the given enum value.
29+
/// </summary>
30+
/// <typeparam name="T">The type of the enum.</typeparam>
31+
/// <param name="flags">The enum value to remove flags from.</param>
32+
/// <param name="oldFlags">The flags to remove.</param>
33+
/// <returns>The enum value with the specified flags removed.</returns>
34+
public static T RemoveFlags<T>(this T flags, params T[] oldFlags)
35+
where T : Enum => flags.ModifyFlags(false, oldFlags);
36+
37+
/// <summary>
38+
/// Sets the specified flag to the given value, default is true.
39+
/// </summary>
40+
/// <param name="flags">The flags enum to modify.</param>
41+
/// <param name="value">The value to set the flag to.</param>
42+
/// <param name="changeFlags">The flags to modify.</param>
43+
/// <typeparam name="T">The type of the enum.</typeparam>
44+
/// <returns>The flags enum with the flag set to the given value.</returns>
45+
public static T ModifyFlags<T>(this T flags, bool value, params T[] changeFlags)
46+
where T : Enum
47+
{
48+
long currentValue = Convert.ToInt64(flags);
49+
50+
foreach (T flag in changeFlags)
51+
{
52+
long flagValue = Convert.ToInt64(flag);
53+
54+
if (value)
55+
currentValue |= flagValue;
56+
else
57+
currentValue &= ~flagValue;
58+
}
59+
60+
return (T)Enum.ToObject(typeof(T), currentValue);
61+
}
62+
}
63+
}

EXILED/Exiled.API/Extensions/MirrorExtensions.cs

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -435,12 +435,11 @@ public static void SendFakeTargetRpc(Player target, NetworkIdentity behaviorOwne
435435
/// <example>
436436
/// EffectOnlySCP207.
437437
/// <code>
438-
/// MirrorExtensions.SendCustomSync(player, player.ReferenceHub.networkIdentity, typeof(PlayerEffectsController), (writer) => {
439-
/// writer.WriteUInt64(1ul); // DirtyObjectsBit
440-
/// writer.WriteUInt32(1); // DirtyIndexCount
438+
/// MirrorExtensions.SendFakeSyncObject(player, player.NetworkIdentity, typeof(PlayerEffectsController), (writer) => {
439+
/// writer.WriteULong(1ul); // DirtyObjectsBit
440+
/// writer.WriteUInt(1); // DirtyIndexCount
441441
/// writer.WriteByte((byte)SyncList&lt;byte&gt;.Operation.OP_SET); // Operations
442-
/// writer.WriteUInt32(17); // EditIndex
443-
/// writer.WriteByte(1); // Value
442+
/// writer.WriteUInt(17); // EditIndex
444443
/// });
445444
/// </code>
446445
/// </example>

EXILED/Exiled.API/Extensions/RoleExtensions.cs

Lines changed: 13 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -140,18 +140,22 @@ public static SpawnLocation GetRandomSpawnLocation(this RoleTypeId roleType)
140140
return null;
141141
}
142142

143+
/// <summary>
144+
/// Gets the starting <see cref="InventoryRoleInfo"/> of a <see cref="RoleTypeId"/>.
145+
/// </summary>
146+
/// <param name="role">The <see cref="RoleTypeId"/>.</param>
147+
/// <returns>The <see cref="InventoryRoleInfo"/> that the role receives on spawn. </returns>
148+
public static InventoryRoleInfo GetInventory(this RoleTypeId role)
149+
=> StartingInventories.DefinedInventories.TryGetValue(role, out InventoryRoleInfo info)
150+
? info
151+
: new(Array.Empty<ItemType>(), new());
152+
143153
/// <summary>
144154
/// Gets the starting items of a <see cref="RoleTypeId"/>.
145155
/// </summary>
146156
/// <param name="roleType">The <see cref="RoleTypeId"/>.</param>
147157
/// <returns>An <see cref="Array"/> of <see cref="ItemType"/> that the role receives on spawn. Will be empty for classes that do not spawn with items.</returns>
148-
public static ItemType[] GetStartingInventory(this RoleTypeId roleType)
149-
{
150-
if (StartingInventories.DefinedInventories.TryGetValue(roleType, out InventoryRoleInfo info))
151-
return info.Items;
152-
153-
return Array.Empty<ItemType>();
154-
}
158+
public static ItemType[] GetStartingInventory(this RoleTypeId roleType) => GetInventory(roleType).Items;
155159

156160
/// <summary>
157161
/// Gets the starting ammo of a <see cref="RoleTypeId"/>.
@@ -160,10 +164,9 @@ public static ItemType[] GetStartingInventory(this RoleTypeId roleType)
160164
/// <returns>An <see cref="Array"/> of <see cref="ItemType"/> that the role receives on spawn. Will be empty for classes that do not spawn with ammo.</returns>
161165
public static Dictionary<AmmoType, ushort> GetStartingAmmo(this RoleTypeId roleType)
162166
{
163-
if (StartingInventories.DefinedInventories.TryGetValue(roleType, out InventoryRoleInfo info))
164-
return info.Ammo.ToDictionary(kvp => kvp.Key.GetAmmoType(), kvp => kvp.Value);
167+
InventoryRoleInfo info = roleType.GetInventory();
165168

166-
return new();
169+
return info.Ammo.ToDictionary(kvp => kvp.Key.GetAmmoType(), kvp => kvp.Value);
167170
}
168171
}
169172
}

EXILED/Exiled.API/Extensions/StringExtensions.cs

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -161,7 +161,11 @@ public static string GetBefore(this string input, char symbol)
161161
/// </summary>
162162
/// <param name="userId">The user id.</param>
163163
/// <returns>Returns the raw user id.</returns>
164-
public static string GetRawUserId(this string userId) => userId.Substring(0, userId.LastIndexOf('@'));
164+
public static string GetRawUserId(this string userId)
165+
{
166+
int index = userId.IndexOf('@');
167+
return index == -1 ? userId : userId.Substring(0, index);
168+
}
165169

166170
/// <summary>
167171
/// Gets a SHA256 hash of a player's user id without the authentication.

EXILED/Exiled.API/Features/Camera.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@ public class Camera : IWrapper<Scp079Camera>, IWorldSpace
2828
/// <summary>
2929
/// A <see cref="Dictionary{TKey,TValue}"/> containing all known <see cref="Scp079Camera"/>s and their corresponding <see cref="Camera"/>.
3030
/// </summary>
31-
internal static readonly Dictionary<Scp079Camera, Camera> Camera079ToCamera = new(250);
31+
internal static readonly Dictionary<Scp079Camera, Camera> Camera079ToCamera = new(250, new ComponentsEqualityComparer());
3232

3333
private static readonly Dictionary<string, CameraType> NameToCameraType = new()
3434
{

EXILED/Exiled.API/Features/Doors/AirlockController.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ public class AirlockController
2020
/// <summary>
2121
/// A <see cref="Dictionary{TKey,TValue}"/> containing all known <see cref="BaseController"/>'s and their corresponding <see cref="AirlockController"/>.
2222
/// </summary>
23-
internal static readonly Dictionary<BaseController, AirlockController> BaseToExiledControllers = new();
23+
internal static readonly Dictionary<BaseController, AirlockController> BaseToExiledControllers = new(new ComponentsEqualityComparer());
2424

2525
/// <summary>
2626
/// Initializes a new instance of the <see cref="AirlockController"/> class.

EXILED/Exiled.API/Features/Doors/Door.cs

Lines changed: 44 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,9 @@ namespace Exiled.API.Features.Doors
1414
using Exiled.API.Enums;
1515
using Exiled.API.Extensions;
1616
using Exiled.API.Features.Core;
17+
using Exiled.API.Features.Hazards;
1718
using Exiled.API.Interfaces;
19+
using global::Hazards;
1820
using Interactables.Interobjects;
1921
using Interactables.Interobjects.DoorUtils;
2022
using MEC;
@@ -38,7 +40,7 @@ public class Door : TypeCastObject<Door>, IWrapper<DoorVariant>, IWorldSpace
3840
/// <summary>
3941
/// A <see cref="Dictionary{TKey,TValue}"/> containing all known <see cref="DoorVariant"/>'s and their corresponding <see cref="Door"/>.
4042
/// </summary>
41-
internal static readonly Dictionary<DoorVariant, Door> DoorVariantToDoor = new();
43+
internal static readonly Dictionary<DoorVariant, Door> DoorVariantToDoor = new(new ComponentsEqualityComparer());
4244

4345
/// <summary>
4446
/// Initializes a new instance of the <see cref="Door"/> class.
@@ -309,6 +311,31 @@ public static Door Get(DoorVariant doorVariant)
309311
return DoorVariantToDoor[doorVariant];
310312
}
311313

314+
/// <summary>
315+
/// Gets the <see cref="Door"/> by <see cref="DoorVariant"/>.
316+
/// </summary>
317+
/// <param name="doorVariant">The <see cref="DoorVariant"/> to convert into an door.</param>
318+
/// <typeparam name="T">The specified <see cref="Door"/> type.</typeparam>
319+
/// <returns>The door wrapper for the given <see cref="DoorVariant"/>.</returns>
320+
public static T Get<T>(DoorVariant doorVariant)
321+
where T : Door => Get(doorVariant) as T;
322+
323+
/// <summary>
324+
/// Gets a <see cref="Door"/> given the specified <see cref="DoorType"/>.
325+
/// </summary>
326+
/// <param name="doorType">The <see cref="DoorType"/> to search for.</param>
327+
/// <returns>The <see cref="Door"/> with the given <see cref="DoorType"/> or <see langword="null"/> if not found.</returns>
328+
public static Door Get(DoorType doorType) => List.FirstOrDefault(x => x.Type == doorType);
329+
330+
/// <summary>
331+
/// Gets the <see cref="Door"/> by <see cref="DoorVariant"/>.
332+
/// </summary>
333+
/// <param name="doorType">The <see cref="DoorVariant"/> to convert into an door.</param>
334+
/// <typeparam name="T">The specified <see cref="Door"/> type.</typeparam>
335+
/// <returns>The door wrapper for the given <see cref="DoorVariant"/>.</returns>
336+
public static T Get<T>(DoorType doorType)
337+
where T : Door => Get(doorType) as T;
338+
312339
/// <summary>
313340
/// Gets a <see cref="Door"/> given the specified name.
314341
/// </summary>
@@ -320,27 +347,22 @@ public static Door Get(string name)
320347
return nameExtension is null ? null : Get(nameExtension.TargetDoor);
321348
}
322349

350+
/// <summary>
351+
/// Gets the <see cref="Door"/> by <see cref="DoorVariant"/>.
352+
/// </summary>
353+
/// <param name="name">The name to search for.</param>
354+
/// <typeparam name="T">The specified <see cref="Door"/> type.</typeparam>
355+
/// <returns>The door wrapper for the given <see cref="DoorVariant"/>.</returns>
356+
public static T Get<T>(string name)
357+
where T : Door => Get(name) as T;
358+
323359
/// <summary>
324360
/// Gets the door object associated with a specific <see cref="UnityEngine.GameObject"/>, or creates a new one if there isn't one.
325361
/// </summary>
326362
/// <param name="gameObject">The base-game <see cref="UnityEngine.GameObject"/>.</param>
327363
/// <returns>The <see cref="Door"/> with the given name or <see langword="null"/> if not found.</returns>
328364
public static Door Get(GameObject gameObject) => gameObject is null ? null : Get(gameObject.GetComponentInChildren<DoorVariant>());
329365

330-
/// <summary>
331-
/// Gets a <see cref="IEnumerable{T}"/> of <see cref="Door"/> filtered based on a predicate.
332-
/// </summary>
333-
/// <param name="predicate">The condition to satify.</param>
334-
/// <returns>A <see cref="IEnumerable{T}"/> of <see cref="Door"/> which contains elements that satify the condition.</returns>
335-
public static IEnumerable<Door> Get(Func<Door, bool> predicate) => List.Where(predicate);
336-
337-
/// <summary>
338-
/// Gets a <see cref="Door"/> given the specified <see cref="DoorType"/>.
339-
/// </summary>
340-
/// <param name="doorType">The <see cref="DoorType"/> to search for.</param>
341-
/// <returns>The <see cref="Door"/> with the given <see cref="DoorType"/> or <see langword="null"/> if not found.</returns>
342-
public static Door Get(DoorType doorType) => List.FirstOrDefault(x => x.Type == doorType);
343-
344366
/// <summary>
345367
/// Returns the closest <see cref="Door"/> to the given <paramref name="position"/>.
346368
/// </summary>
@@ -367,6 +389,13 @@ public static Door Random(ZoneType type = ZoneType.Unspecified, bool onlyUnbroke
367389
return doors[UnityEngine.Random.Range(0, doors.Count)];
368390
}
369391

392+
/// <summary>
393+
/// Gets a <see cref="IEnumerable{T}"/> of <see cref="Door"/> filtered based on a predicate.
394+
/// </summary>
395+
/// <param name="predicate">The condition to satify.</param>
396+
/// <returns>A <see cref="IEnumerable{T}"/> of <see cref="Door"/> which contains elements that satify the condition.</returns>
397+
public static IEnumerable<Door> Get(Func<Door, bool> predicate) => List.Where(predicate);
398+
370399
/// <summary>
371400
/// Locks all <see cref="Door">doors</see> given the specified <see cref="ZoneType"/>.
372401
/// </summary>

0 commit comments

Comments
 (0)