diff --git a/.github/README.md b/.github/README.md new file mode 100644 index 00000000..8aaaa1b0 --- /dev/null +++ b/.github/README.md @@ -0,0 +1,45 @@ +

+ + + + NW logo + + +

+ +

LabAPI

+
SCP: Secret Laboratory's official server-side modding framework.
+
+ Plugins + - + Docs + - + Report Bug + - + Discord +

+
+ +
+ +[![Version](https://img.shields.io/github/v/release/northwood-studios/LabAPI?sort=semver&style=flat-square&color=8DBBE9&label=Version)]() +[![License](https://img.shields.io/github/license/northwood-studios/LabAPI?style=flat-square&label=License&color=df967f)]() +[![Contributors](https://img.shields.io/github/contributors-anon/northwood-studios/LabAPI?color=90E59A&style=flat-square&label=Contributors)]() +[![GitHub Issues](https://img.shields.io/github/issues/northwood-studios/LabAPI.svg?style=flat-square&label=Issues&color=d77982)](https://github.com/northwood-studios/LabAPI/issues) +[![Discord](https://img.shields.io/discord/330432627649544202?color=738adb&label=Discord&logo=discord&logoColor=white&style=flat-square)](https://discord.gg/scpsl) + +
+ +The LabAPI project is **[SCP: Secret Laboratory](https://store.steampowered.com/app/700330/SCP_Secret_Laboratory/)**'s official server-side plugin loader and framework. It facilitates development of plugins by providing wrappers and events around various game mechanics found throughout the game. + +## Documentation +Code should have self-explanatory documentation, but there's only so much you can explain through comments! +- For guides, tips and tricks, our main source of documentation can be found [here](https://github.com/northwood-studios/LabAPI/wiki). +- For a more practical approach, examples can be found [here](https://github.com/northwood-studios/LabAPI/tree/master/LabApi.Examples). + +## Installation +All **SCP: SL Dedicated Server** builds are bundled with a compiled **`LabAPI.dll`**, so you don't need to install it if you are hosting a server. + +However, [releases](https://github.com/northwood-studios/LabAPI/releases) may occasionally occur *before* the dedicated server is updated, while we advice you wait for an official update, you can always apply the updated release manually. + +To do so, you should update the **`LabAPI.dll`** file located within: `%DEDICATED_SERVER_PATH%/SCPSL_Data/Managed/`. \ No newline at end of file diff --git a/.gitlab/issue_templates/New Bug.md b/.gitlab/issue_templates/New Bug.md new file mode 100644 index 00000000..a1b4ffcd --- /dev/null +++ b/.gitlab/issue_templates/New Bug.md @@ -0,0 +1,34 @@ +> **New Issue Guidelines:** (For you! The writer :writing_hand: ) +> - Make sure to only choose one priority level, the bottom of this template has all labels you'll need. Delete the ones you don't need! +> - Mention the affected system in this issue's title. Something like `[RA] Using X throws an exception` or `[Intercom] Talking blows your computer up`. +> - In some cases, remember to verify with the team in charge of this kind of feature. (Examples: Art, Programming, Game Design) + +> **Choose one task priority level:** *(You can delete this line as well)* +/label ~"P1 - Critical" +/label ~"P2 - Priority Issue" +/label ~"P3 - Regular Priority" +/label ~"P4 - Low Priority" + +## Description +> A description about what the issue / bug is. How it affects players. And finally, how it's supposed to function. + +## Replication Steps & Requirements + +### Requirements: +- Have 2 or more players online, they'll be called Hubert & You. (Example) +- Before entering the game, change your Graphic Settings to **Low**. (Example) + +### Replication Steps: +- You must join the server first, without Hubert in it. +- Hubert must then join after you. +- When Hubert spawns, he will appear as a giant pink-textured role. + +## Attachments +> Any sort of video, image, client/server logs, just proof of the reported issue. For example: +- Related issues: #244 #123 #21 #50 +- Replication video: https://www.youtube.com/watch?v=2Q_ZzBGPdqE + +/label ~bug +/label ~todo + +/cc @jesusqc \ No newline at end of file diff --git a/.gitlab/issue_templates/New Idea.md b/.gitlab/issue_templates/New Idea.md new file mode 100644 index 00000000..dc6854b1 --- /dev/null +++ b/.gitlab/issue_templates/New Idea.md @@ -0,0 +1,18 @@ +> **New Issue Guidelines:** (For you! The writer :writing_hand: ) +> - Mention the affected system in this issue's title. Something like `[RA] Custom Menus Idea` or `[Map] New Map Generation Algorithm Ideas`. + +## Description +> A description of what you would like to see implemented, and perhaps how. Can be as vague and informal as you want. However, being descriptive is always appreciated. 😉 + +Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. + +## Notes +> These should serve as a guide of different ideas or concerns you may have regarding task, providing some insight of your vision to the programmer that may work on it. +- Example1. +- Example2. + +# Status +- [ ] **Approved for implementation by LabAPI's Management.** + +/label ~experimental +/confidential \ No newline at end of file diff --git a/.gitlab/issue_templates/New Task - Docless.md b/.gitlab/issue_templates/New Task - Docless.md new file mode 100644 index 00000000..55f021e0 --- /dev/null +++ b/.gitlab/issue_templates/New Task - Docless.md @@ -0,0 +1,17 @@ +/label ~"P1 - Critical" +/label ~"P2 - Priority Issue" +/label ~"P3 - Regular Priority" +/label ~"P4 - Low Priority" + +## Description + + +## Task Expectations/Check-list +- [ ] + +## Assets +- Design Document: + +/label ~"Task / Bounty" +/label ~todo +/confidential \ No newline at end of file diff --git a/.gitlab/issue_templates/New Task.md b/.gitlab/issue_templates/New Task.md new file mode 100644 index 00000000..18ac27d6 --- /dev/null +++ b/.gitlab/issue_templates/New Task.md @@ -0,0 +1,27 @@ +> **New Issue Guidelines:** (For you! The writer :writing_hand: ) +> - Make sure to only choose one priority level, the bottom of this template has all labels you'll need. Delete the ones you don't need! +> - Mention the affected system in this issue's title. Something like `[RA] Using X throws an exception` or `[Intercom] Talking blows your computer up`. + +> **Choose one task priority level:** *(You can delete this line as well)* +/label ~"P1 - Critical" +/label ~"P2 - Priority Issue" +/label ~"P3 - Regular Priority" +/label ~"P4 - Low Priority" + +## Description +> A description about what the task is and possibly an idea of how to implement if possible. + +## Task Expectations/Check-list +> **As always,** read the design document before starting work on it (if one was attached), the check-list below is merely done to help assignees follow some steps and not get lost. :smile: +- [ ] Text. +- [ ] Text2. +- [ ] Text3. + +## Assets +> Any assets that the assignee will need to complete this task / implement this feature. Make sure to include the **Design Document** here. +- Asset1. +- Asset2. + +/label ~"Task / Bounty" +/label ~todo +/confidential \ No newline at end of file diff --git a/.gitlab/merge_request_templates/MR Template - Docless.md b/.gitlab/merge_request_templates/MR Template - Docless.md new file mode 100644 index 00000000..3de19d68 --- /dev/null +++ b/.gitlab/merge_request_templates/MR Template - Docless.md @@ -0,0 +1,20 @@ +## Changes + +### Changelog +```yml +- +``` + +## Relevant Issues / Tasks + +Resolves #X + +## Notes (Optional) + + + +# **Status** +- [ ] **Approved by QA.** + +/ready +/done \ No newline at end of file diff --git a/.gitlab/merge_request_templates/MR Template.md b/.gitlab/merge_request_templates/MR Template.md new file mode 100644 index 00000000..a75c866a --- /dev/null +++ b/.gitlab/merge_request_templates/MR Template.md @@ -0,0 +1,22 @@ +## Changes + +### Changelog +> These should stay technical, you don't have to mention exactly what you did step-by-step, but providing something for other programmers to check on later is preferred. Studio Staff in charge of public announcements will use this changelog to create a simplified version of it. +```yml +- Text +``` + +## Relevant Issues / Tasks (Optional) + +> Replace the `X` with the issue ID you wish to automatically close when this is merged. +Resolves #X + +## Notes (Optional) + +> Write down any additional related notes programmers or the current lead programmer should be aware of regarding this merge request. + +# **Status** +- [ ] **Approved by QA.** + +/ready +/done \ No newline at end of file diff --git a/LabApi.Examples/LogAll/LogPlugin/LogPlugin.csproj b/LabApi.Examples/LogAll/LogPlugin/LogPlugin.csproj index 2fd62420..d546ec6e 100644 --- a/LabApi.Examples/LogAll/LogPlugin/LogPlugin.csproj +++ b/LabApi.Examples/LogAll/LogPlugin/LogPlugin.csproj @@ -15,6 +15,7 @@ + diff --git a/LabApi.Examples/LogAll/LogPlugin/MyCustomEventsHandler.cs b/LabApi.Examples/LogAll/LogPlugin/MyCustomEventsHandler.cs index 69fac15b..8c00e2d3 100644 --- a/LabApi.Examples/LogAll/LogPlugin/MyCustomEventsHandler.cs +++ b/LabApi.Examples/LogAll/LogPlugin/MyCustomEventsHandler.cs @@ -1,13 +1,17 @@ using System.Linq; +using LabApi.Events.Arguments.ObjectiveEvents; using LabApi.Events.Arguments.PlayerEvents; using LabApi.Events.Arguments.Scp0492Events; using LabApi.Events.Arguments.Scp049Events; using LabApi.Events.Arguments.Scp079Events; using LabApi.Events.Arguments.Scp096Events; using LabApi.Events.Arguments.Scp106Events; +using LabApi.Events.Arguments.Scp127Events; using LabApi.Events.Arguments.Scp173Events; +using LabApi.Events.Arguments.Scp3114Events; using LabApi.Events.Arguments.Scp914Events; using LabApi.Events.Arguments.Scp939Events; +using LabApi.Events.Arguments.ScpEvents; using LabApi.Events.Arguments.ServerEvents; using LabApi.Events.Arguments.WarheadEvents; using LabApi.Events.CustomHandlers; @@ -26,7 +30,7 @@ public override void OnPlayerActivatedGenerator(PlayerActivatedGeneratorEventArg { Logger.Info($"{nameof(OnPlayerActivatedGenerator)} triggered by {ev.Player.UserId}"); } - + public override void OnPlayerUnlockingGenerator(PlayerUnlockingGeneratorEventArgs ev) { Logger.Info($"{nameof(OnPlayerUnlockingGenerator)} triggered by {ev.Player.UserId}"); @@ -36,7 +40,7 @@ public override void OnPlayerUnlockedGenerator(PlayerUnlockedGeneratorEventArgs { Logger.Info($"{nameof(OnPlayerUnlockedGenerator)} triggered by {ev.Player.UserId}"); } - + public override void OnPlayerUnlockingWarheadButton(PlayerUnlockingWarheadButtonEventArgs ev) { Logger.Info($"{nameof(OnPlayerUnlockingWarheadButton)} triggered by {ev.Player.UserId}"); @@ -97,6 +101,16 @@ public override void OnPlayerChangedNickname(PlayerChangedNicknameEventArgs ev) Logger.Info($"{nameof(OnPlayerChangedNickname)} triggered by {ev.Player.UserId}"); } + public override void OnPlayerChangingBadgeVisibility(PlayerChangingBadgeVisibilityEventArgs ev) + { + Logger.Info($"{nameof(OnPlayerChangingBadgeVisibility)} triggered by {ev.Player.UserId}"); + } + + public override void OnPlayerChangedBadgeVisibility(PlayerChangedBadgeVisibilityEventArgs ev) + { + Logger.Info($"{nameof(OnPlayerChangedBadgeVisibility)} triggered by {ev.Player.UserId}"); + } + public override void OnPlayerChangingRadioRange(PlayerChangingRadioRangeEventArgs ev) { Logger.Info($"{nameof(OnPlayerChangingRadioRange)} triggered by {ev.Player.UserId}"); @@ -457,6 +471,16 @@ public override void OnPlayerPreAuthenticated(PlayerPreAuthenticatedEventArgs ev Logger.Info($"{nameof(OnPlayerPreAuthenticated)} triggered by {ev.UserId}"); } + public override void OnPlayerProcessingJailbirdMessage(PlayerProcessingJailbirdMessageEventArgs ev) + { + Logger.Info($"{nameof(OnPlayerProcessingJailbirdMessage)} triggered by {ev.Player.UserId}"); + } + + public override void OnPlayerProcessedJailbirdMessage(PlayerProcessedJailbirdMessageEventArgs ev) + { + Logger.Info($"{nameof(OnPlayerProcessedJailbirdMessage)} triggered by {ev.Player.UserId}"); + } + public override void OnPlayerUpdatingEffect(PlayerEffectUpdatingEventArgs ev) { Logger.Info($"{nameof(OnPlayerUpdatingEffect)} triggered by {ev.Player.UserId}"); @@ -467,6 +491,56 @@ public override void OnPlayerUpdatedEffect(PlayerEffectUpdatedEventArgs ev) Logger.Info($"{nameof(OnPlayerUpdatedEffect)} triggered by {ev.Player.UserId}"); } + public override void OnPlayerRaPlayerListAddedPlayer(PlayerRaPlayerListAddedPlayerEventArgs ev) + { + Logger.Info($"{nameof(OnPlayerRaPlayerListAddedPlayer)} triggered by {ev.Player.UserId}"); + } + + public override void OnPlayerRaPlayerListAddingPlayer(PlayerRaPlayerListAddingPlayerEventArgs ev) + { + Logger.Info($"{nameof(OnPlayerRaPlayerListAddingPlayer)} triggered by {ev.Player.UserId}"); + } + + public override void OnPlayerReceivedAchievement(PlayerReceivedAchievementEventArgs ev) + { + Logger.Info($"{nameof(OnPlayerReceivedAchievement)} triggered by {ev.Player?.UserId ?? "unknown"}"); + } + + public override void OnPlayerRequestedCustomRaInfo(PlayerRequestedCustomRaInfoEventArgs ev) + { + Logger.Info($"{nameof(OnPlayerRequestedCustomRaInfo)} triggered by {ev.Player.UserId}"); + } + + public override void OnPlayerRequestedRaPlayerInfo(PlayerRequestedRaPlayerInfoEventArgs ev) + { + Logger.Info($"{nameof(OnPlayerRequestedRaPlayerInfo)} triggered by {ev.Player.UserId}"); + } + + public override void OnPlayerRequestedRaPlayerList(PlayerRequestedRaPlayerListEventArgs ev) + { + Logger.Info($"{nameof(OnPlayerRequestedRaPlayerList)} triggered by {ev.Player.UserId}"); + } + + public override void OnPlayerRequestedRaPlayersInfo(PlayerRequestedRaPlayersInfoEventArgs ev) + { + Logger.Info($"{nameof(OnPlayerRequestedRaPlayersInfo)} triggered by {ev.Player.UserId}"); + } + + public override void OnPlayerRequestingRaPlayerInfo(PlayerRequestingRaPlayerInfoEventArgs ev) + { + Logger.Info($"{nameof(OnPlayerRequestingRaPlayerInfo)} triggered by {ev.Player.UserId}"); + } + + public override void OnPlayerRequestingRaPlayerList(PlayerRequestingRaPlayerListEventArgs ev) + { + Logger.Info($"{nameof(OnPlayerRequestingRaPlayerList)} triggered by {ev.Player.UserId}"); + } + + public override void OnPlayerRequestingRaPlayersInfo(PlayerRequestingRaPlayersInfoEventArgs ev) + { + Logger.Info($"{nameof(OnPlayerRequestingRaPlayersInfo)} triggered by {ev.Player.UserId}"); + } + //public override void OnPlayerReceivingVoiceMessage(PlayerReceivingVoiceMessageEventArgs ev) //{ // Logger.Info($"{nameof(OnPlayerReceivingVoiceMessage)} triggered by {ev.Player.UserId}"); @@ -702,6 +776,11 @@ public override void OnPlayerUsedItem(PlayerUsedItemEventArgs ev) Logger.Info($"{nameof(OnPlayerUsedItem)} triggered by {ev.Player.UserId}"); } + public override void OnPlayerItemUsageEffectsApplying(PlayerItemUsageEffectsApplyingEventArgs ev) + { + Logger.Info($"{nameof(OnPlayerItemUsageEffectsApplying)} triggered by {ev.Player.UserId}"); + } + public override void OnPlayerTogglingNoclip(PlayerTogglingNoclipEventArgs ev) { Logger.Info($"{nameof(OnPlayerTogglingNoclip)} triggered by {ev.Player.UserId}"); @@ -737,6 +816,26 @@ public override void OnPlayerLeftHazard(PlayerLeftHazardEventArgs ev) Logger.Info($"{nameof(OnPlayerLeftHazard)} triggered by {ev.Player.UserId}"); } + public override void OnScp049Attacking(Scp049AttackingEventArgs ev) + { + Logger.Info($"{nameof(OnScp049Attacking)} triggered by {ev.Player} {ev.Target} {ev.InstantKill} {ev.IsSenseTarget} {ev.CooldownTime}"); + } + + public override void OnScp049Attacked(Scp049AttackedEventArgs ev) + { + Logger.Info($"{nameof(OnScp049Attacked)} triggered by {ev.Player} {ev.Target} {ev.InstantKill} {ev.IsSenseTarget}"); + } + + public override void OnScp049SenseKilledTarget(Scp049SenseKilledTargetEventArgs ev) + { + Logger.Info($"{nameof(OnScp049SenseKilledTarget)} triggered by {ev.Player} {ev.Target}"); + } + + public override void OnScp049SenseLostTarget(Scp049SenseLostTargetEventArgs ev) + { + Logger.Info($"{nameof(OnScp049SenseLostTarget)} triggered by {ev.Player} {ev.Target}"); + } + public override void OnScp049StartingResurrection(Scp049StartingResurrectionEventArgs ev) { Logger.Info($"{nameof(OnScp049StartingResurrection)} triggered by {ev.Player.UserId}"); @@ -1072,6 +1171,36 @@ public override void OnScp173PlayedSound(Scp173PlayedSoundEventArgs ev) Logger.Info($"{nameof(OnScp173PlayedSound)} triggered by {ev.Player.UserId}"); } + public override void OnScp173Snapped(Scp173SnappedEventArgs ev) + { + Logger.Info($"{nameof(OnScp173Snapped)} triggered by {ev.Player.UserId} targeting {ev.Target.UserId}"); + } + + public override void OnScp173Snapping(Scp173SnappingEventArgs ev) + { + Logger.Info($"{nameof(OnScp173Snapping)} triggered by {ev.Player.UserId} targeting {ev.Target.UserId}"); + } + + public override void OnScp3114StrangleAborting(Scp3114StrangleAbortingEventArgs ev) + { + Logger.Info($"{nameof(OnScp3114StrangleAborting)} triggered by {ev.Player.UserId}"); + } + + public override void OnScp3114StrangleAborted(Scp3114StrangleAbortedEventArgs ev) + { + Logger.Info($"{nameof(OnScp3114StrangleAborted)} triggered by {ev.Player.UserId}"); + } + + public override void OnScp3114StrangleStarting(Scp3114StrangleStartingEventArgs ev) + { + Logger.Info($"{nameof(OnScp3114StrangleStarting)} triggered by {ev.Player.UserId}"); + } + + public override void OnScp3114StrangleStarted(Scp3114StrangleStartedEventArgs ev) + { + Logger.Info($"{nameof(OnScp3114StrangleStarted)} triggered by {ev.Player.UserId}"); + } + public override void OnScp914Activating(Scp914ActivatingEventArgs ev) { Logger.Info($"{nameof(OnScp914Activating)} triggered by {ev.Player.UserId}"); @@ -1311,7 +1440,7 @@ public override void OnServerCassieQueuingScpTermination(CassieQueuingScpTermina { Logger.Info($"{nameof(OnServerCassieQueuingScpTermination)} triggered"); } - + public override void OnServerCassieQueuedScpTermination(CassieQueuedScpTerminationEventArgs ev) { Logger.Info($"{nameof(OnServerCassieQueuedScpTermination)} triggered"); @@ -1376,8 +1505,282 @@ public override void OnWarheadDetonated(WarheadDetonatedEventArgs ev) { Logger.Info($"{nameof(OnWarheadDetonated)} triggered by {ev.Player.UserId}"); } + + public override void OnObjectiveCompleting(ObjectiveCompletingBaseEventArgs ev) + { + Logger.Info($"{nameof(OnObjectiveCompleting)} triggered by {ev.Player.UserId}"); + } + + public override void OnObjectiveCompleted(ObjectiveCompletedBaseEventArgs ev) + { + Logger.Info($"{nameof(OnObjectiveCompleted)} triggered by {ev.Player.UserId}"); + } + + public override void OnObjectiveActivatedGeneratorCompleted(GeneratorActivatedObjectiveEventArgs ev) + { + Logger.Info($"{nameof(OnObjectiveActivatedGeneratorCompleted)} triggered by {ev.Player.UserId}"); + } + + public override void OnObjectiveActivatingGeneratorCompleting(GeneratorActivatingObjectiveEventArgs ev) + { + Logger.Info($"{nameof(OnObjectiveActivatingGeneratorCompleting)} triggered by {ev.Player.UserId}"); + } + + public override void OnObjectiveDamagedScpCompleted(ScpDamagedObjectiveEventArgs ev) + { + Logger.Info($"{nameof(OnObjectiveDamagedScpCompleted)} triggered by {ev.Player.UserId}"); + } + + public override void OnObjectiveDamagingScpCompleting(ScpDamagingObjectiveEventArgs ev) + { + Logger.Info($"{nameof(OnObjectiveDamagingScpCompleting)} triggered by {ev.Player.UserId}"); + } + + public override void OnObjectiveEscapingCompleting(EscapingObjectiveEventArgs ev) + { + Logger.Info($"{nameof(OnObjectiveEscapingCompleting)} triggered by {ev.Player.UserId}"); + } + + public override void OnObjectiveEscapedCompleted(EscapedObjectiveEventArgs ev) + { + Logger.Info($"{nameof(OnObjectiveEscapedCompleted)} triggered by {ev.Player.UserId}"); + } + + public override void OnObjectiveKillingEnemyCompleting(EnemyKillingObjectiveEventArgs ev) + { + Logger.Info($"{nameof(OnObjectiveKillingEnemyCompleting)} triggered by {ev.Player.UserId}"); + } + + public override void OnObjectiveKilledEnemyCompleted(EnemyKilledObjectiveEventArgs ev) + { + Logger.Info($"{nameof(OnObjectiveKilledEnemyCompleted)} triggered by {ev.Player.UserId}"); + } + + public override void OnObjectivePickingScpItemCompleting(ScpItemPickingObjectiveEventArgs ev) + { + Logger.Info($"{nameof(OnObjectivePickingScpItemCompleting)} triggered by {ev.Player.UserId}"); + } + + public override void OnObjectivePickedScpItemCompleted(ScpItemPickedObjectiveEventArgs ev) + { + Logger.Info($"{nameof(OnObjectivePickedScpItemCompleted)} triggered by {ev.Player.UserId}"); + } + + public override void OnPlayerJumped(PlayerJumpedEventArgs ev) + { + Logger.Info($"{nameof(OnPlayerJumped)} triggered by {ev.Player.UserId}"); + } + + public override void OnPlayerMovementStateChanged(PlayerMovementStateChangedEventArgs ev) + { + Logger.Info($"{nameof(OnPlayerMovementStateChanged)} triggered by {ev.Player.UserId}"); + } + + public override void OnPlayerChangingAttachments(PlayerChangingAttachmentsEventArgs ev) + { + Logger.Info($"{nameof(OnPlayerChangingAttachments)} triggered by {ev.Player.UserId}"); + } + + public override void OnPlayerChangedAttachments(PlayerChangedAttachmentsEventArgs ev) + { + Logger.Info($"{nameof(OnPlayerChangedAttachments)} triggered by {ev.Player.UserId}"); + } + + public override void OnPlayerSendingAttachmentsPrefs(PlayerSendingAttachmentsPrefsEventArgs ev) + { + Logger.Info($"{nameof(OnPlayerSendingAttachmentsPrefs)} triggered by {ev.Player.UserId}"); + } + + public override void OnPlayerSentAttachmentsPrefs(PlayerSentAttachmentsPrefsEventArgs ev) + { + Logger.Info($"{nameof(OnPlayerSentAttachmentsPrefs)} triggered by {ev.Player.UserId}"); + } + + public override void OnServerElevatorSequenceChanged(ElevatorSequenceChangedEventArgs ev) + { + Logger.Info($"{nameof(OnServerElevatorSequenceChanged)} triggered"); + } + + public override void OnPlayerInteractingWarheadLever(PlayerInteractingWarheadLeverEventArgs ev) + { + Logger.Info($"{nameof(OnPlayerInteractingWarheadLever)} triggered by {ev.Player.UserId}"); + } + + public override void OnPlayerInteractedWarheadLever(PlayerInteractedWarheadLeverEventArgs ev) + { + Logger.Info($"{nameof(OnPlayerInteractedWarheadLever)} triggered by {ev.Player.UserId}"); + } + + public override void OnScp3114Disguising(Scp3114DisguisingEventArgs ev) + { + Logger.Info($"{nameof(OnScp3114Disguising)} triggered by {ev.Player.UserId}"); + } + + public override void OnScp3114Disguised(Scp3114DisguisedEventArgs ev) + { + Logger.Info($"{nameof(OnScp3114Disguised)} triggered by {ev.Player.UserId}"); + } + + public override void OnScp3114Revealing(Scp3114RevealingEventArgs ev) + { + Logger.Info($"{nameof(OnScp3114Revealing)} triggered by {ev.Player.UserId}"); + } + + public override void OnScp3114Revealed(Scp3114RevealedEventArgs ev) + { + Logger.Info($"{nameof(OnScp3114Revealed)} triggered by {ev.Player.UserId}"); + } + + public override void OnScp3114StartDancing(Scp3114StartingDanceEventArgs ev) + { + Logger.Info($"{nameof(OnScp3114StartDancing)} triggered by {ev.Player.UserId}"); + } + + public override void OnScp3114Dance(Scp3114StartedDanceEventArgs ev) + { + Logger.Info($"{nameof(OnScp3114Dance)} triggered by {ev.Player.UserId}"); + } + + public override void OnPlayerToggledDisruptorFiringMode(PlayerToggledDisruptorFiringModeEventArgs ev) + { + Logger.Info($"{nameof(OnPlayerToggledDisruptorFiringMode)} triggered by {ev.Player.UserId}"); + } + + public override void OnPlayerSpinningRevolver(PlayerSpinningRevolverEventArgs ev) + { + Logger.Info($"{nameof(OnPlayerSpinningRevolver)} triggered by {ev.Player.UserId}"); + } + + public override void OnPlayerSpinnedRevolver(PlayerSpinnedRevolverEventArgs ev) + { + Logger.Info($"{nameof(OnPlayerSpinnedRevolver)} triggered by {ev.Player.UserId}"); + } + + public override void OnScp127GainingExperience(Scp127GainingExperienceEventArgs ev) + { + Logger.Info($"{nameof(OnScp127GainingExperience)} triggered by {ev.Scp127Item.CurrentOwner}"); + } + + public override void OnScp127GainExperience(Scp127GainExperienceEventArgs ev) + { + Logger.Info($"{nameof(OnScp127GainExperience)} triggered by {ev.Scp127Item.CurrentOwner}"); + } + + public override void OnScp127LevellingUp(Scp127LevellingUpEventArgs ev) + { + Logger.Info($"{nameof(OnScp127LevellingUp)} triggered by {ev.Scp127Item.CurrentOwner}"); + } + + public override void OnScp127LevelUp(Scp127LevelUpEventArgs ev) + { + Logger.Info($"{nameof(OnScp127LevelUp)} triggered by {ev.Scp127Item.CurrentOwner}"); + } + + public override void OnScp127Talking(Scp127TalkingEventArgs ev) + { + Logger.Info($"{nameof(OnScp127Talking)} triggered by {ev.Scp127Item.CurrentOwner}"); + } + + public override void OnScp127Talked(Scp127TalkedEventArgs ev) + { + Logger.Info($"{nameof(OnScp127Talked)} triggered by {ev.Scp127Item.CurrentOwner}"); + } - + public override void OnPlayerCheckedHitmarker(PlayerCheckedHitmarkerEventArgs ev) + { + Logger.Info($"{nameof(OnPlayerCheckedHitmarker)} triggered by {ev.Player} {ev.Victim} {ev.Result}"); + } + + public override void OnPlayerSentHitmarker(PlayerSentHitmarkerEventArgs ev) + { + Logger.Info($"{nameof(OnPlayerSentHitmarker)} triggered by {ev.Player} {ev.Size} {ev.PlayedAudio}"); + } + + public override void OnPlayerSendingHitmarker(PlayerSendingHitmarkerEventArgs ev) + { + Logger.Info($"{nameof(OnPlayerSendingHitmarker)} triggered by {ev.Player} {ev.Size} {ev.PlayAudio}"); + } + + public override void OnScpHumeShieldBroken(ScpHumeShieldBrokenEventArgs ev) + { + Logger.Info($"{nameof(OnScpHumeShieldBroken)} triggered by {ev.Player}"); + } + + public override void OnServerAchievedMilestone(AchievedMilestoneEventArgs ev) + { + Logger.Info($"{nameof(OnServerAchievedMilestone)} triggered by {ev.Faction} {ev.Threshold} {ev.MilestoneIndex}"); + } + + public override void OnServerAchievingMilestone(AchievingMilestoneEventArgs ev) + { + Logger.Info($"{nameof(OnServerAchievingMilestone)} triggered by {ev.Faction} {ev.Threshold} {ev.MilestoneIndex}"); + } + + public override void OnServerModifiedFactionInfluence(ModifiedFactionInfluenceEventArgs ev) + { + Logger.Info($"{nameof(OnServerModifiedFactionInfluence)} triggered by {ev.Faction} {ev.Influence}"); + } + + public override void OnServerModifyingFactionInfluence(ModifyingFactionInfluenceEventArgs ev) + { + Logger.Info($"{nameof(OnServerModifyingFactionInfluence)} triggered by {ev.Faction} {ev.Influence}"); + } + + public override void OnServerBlastDoorChanged(BlastDoorChangedEventArgs ev) + { + Logger.Info($"{nameof(OnServerBlastDoorChanged)} triggered by {ev.BlastDoor} {ev.NewState}"); + } + + public override void OnServerBlastDoorChanging(BlastDoorChangingEventArgs ev) + { + Logger.Info($"{nameof(OnServerBlastDoorChanging)} triggered by {ev.BlastDoor} {ev.NewState}"); + } + + public override void OnServerDoorDamaged(DoorDamagedEventArgs ev) + { + Logger.Info($"{nameof(OnServerDoorDamaged)} triggered by {ev.Door} {ev.Damage} {ev.DamageType}"); + } + + public override void OnServerDoorDamaging(DoorDamagingEventArgs ev) + { + Logger.Info($"{nameof(OnServerDoorDamaging)} triggered by {ev.Door} {ev.Damage} {ev.DamageType}"); + } + + public override void OnServerDoorLockChanged(DoorLockChangedEventArgs ev) + { + Logger.Info($"{nameof(OnServerDoorLockChanged)} triggered by {ev.Door} {ev.PrevLockReason} => {ev.LockReason}"); + } + + public override void OnServerDoorRepaired(DoorRepairedEventArgs ev) + { + Logger.Info($"{nameof(OnServerDoorRepaired)} triggered by {ev.Door} {ev.RemainingHealth}"); + } + + public override void OnServerDoorRepairing(DoorRepairingEventArgs ev) + { + Logger.Info($"{nameof(OnServerDoorRepairing)} triggered by {ev.Door} {ev.RemainingHealth}"); + } + + public override void OnServerCheckpointDoorSequenceChanged(CheckpointDoorSequenceChangedEventArgs ev) + { + Logger.Info($"{nameof(OnServerCheckpointDoorSequenceChanged)} triggered by {ev.CheckpointDoor} {ev.CurrentSequence}"); + } + + public override void OnServerCheckpointDoorSequenceChanging(CheckpointDoorSequenceChangingEventArgs ev) + { + Logger.Info($"{nameof(OnServerCheckpointDoorSequenceChanging)} triggered by {ev.CheckpointDoor} {ev.CurrentSequence} {ev.NewSequence}"); + } + + public override void OnServerRoomColorChanged(RoomColorChangedEventArgs ev) + { + Logger.Info($"{nameof(OnServerRoomColorChanged)} triggered by {ev.Room} {ev.NewState}"); + } + + public override void OnServerRoomLightChanged(RoomLightChangedEventArgs ev) + { + Logger.Info($"{nameof(OnServerRoomLightChanged)} triggered by {ev.Room} {ev.NewState}"); + } + #region Excluded Events // The following events spam the console and are therefore excluded from this example: diff --git a/LabApi.sln b/LabApi.sln index 264f4e50..208d8a88 100644 --- a/LabApi.sln +++ b/LabApi.sln @@ -25,7 +25,12 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Commands", "Commands", "{3B EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "CommandsPlugin", "LabApi.Examples\Commands\CommandsPlugin\CommandsPlugin.csproj", "{DFDB27D3-70C9-44A6-B2D3-6D8D0716D6FC}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "CommandsPlugin2", "LabApi.Examples\Commands\CommandsPlugin2\CommandsPlugin2.csproj", "{295205EA-B4A2-42CF-8B91-7F9BF6909694}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "CommandsPlugin2", "LabApi.Examples\Commands\CommandsPlugin2\CommandsPlugin2.csproj", "{295205EA-B4A2-42CF-8B91-7F9BF6909694}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{9FDD2A60-56E4-4E77-9E87-B62F3BF06CC8}" + ProjectSection(SolutionItems) = preProject + StyleCopAnalyzers.ruleset = StyleCopAnalyzers.ruleset + EndProjectSection EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution diff --git a/LabApi/Events/Arguments/Interfaces/Hazards/IHazardEvent.cs b/LabApi/Events/Arguments/Interfaces/Hazards/IHazardEvent.cs index 159767d3..b77c4717 100644 --- a/LabApi/Events/Arguments/Interfaces/Hazards/IHazardEvent.cs +++ b/LabApi/Events/Arguments/Interfaces/Hazards/IHazardEvent.cs @@ -12,4 +12,3 @@ public interface IHazardEvent /// public Hazard? Hazard { get; } } - diff --git a/LabApi/Events/Arguments/Interfaces/IGroupEvent.cs b/LabApi/Events/Arguments/Interfaces/IGroupEvent.cs index 0f1d3f9c..06164ad9 100644 --- a/LabApi/Events/Arguments/Interfaces/IGroupEvent.cs +++ b/LabApi/Events/Arguments/Interfaces/IGroupEvent.cs @@ -1,4 +1,5 @@ namespace LabApi.Events.Arguments.Interfaces; + /// /// Represents an event that involves a . /// diff --git a/LabApi/Events/Arguments/Interfaces/IObjectiveEvent.cs b/LabApi/Events/Arguments/Interfaces/IObjectiveEvent.cs new file mode 100644 index 00000000..2bec4f79 --- /dev/null +++ b/LabApi/Events/Arguments/Interfaces/IObjectiveEvent.cs @@ -0,0 +1,39 @@ +using LabApi.Features.Wrappers; +using PlayerRoles; +using Respawning.Objectives; + +namespace LabApi.Events.Arguments.Interfaces; + +/// +/// Represents an event that involves . +/// +public interface IObjectiveEvent +{ + /// + /// Gets the player who triggered the objective completion. + /// + public Player Player { get; } + + /// + /// Gets the which will receive the and rewards. + /// + public Faction Faction { get; } + + /// + /// Gets the amount of influence to grant to the . + /// + public float InfluenceToGrant { get; } + + /// + /// Gets the amount of time to be reduced from the 's timer. + /// + /// + /// Negative values reduce the timer, positive extends it. + /// + public float TimeToGrant { get; } + + /// + /// Gets whether the objective completion should be sent to players and visible on their screen. + /// + public bool SendToPlayers { get; } +} diff --git a/LabApi/Events/Arguments/Interfaces/Items/Firearms/IRevolverItemEvent.cs b/LabApi/Events/Arguments/Interfaces/Items/Firearms/IRevolverItemEvent.cs new file mode 100644 index 00000000..24d0777a --- /dev/null +++ b/LabApi/Events/Arguments/Interfaces/Items/Firearms/IRevolverItemEvent.cs @@ -0,0 +1,17 @@ +using LabApi.Features.Wrappers; + +namespace LabApi.Events.Arguments.Interfaces; + +/// +/// Represents an event that involves a revolver. +/// +public interface IRevolverItemEvent : IItemEvent +{ + /// + Item? IItemEvent.Item => Revolver; + + /// + /// The revolver that is involved in the event. + /// + public RevolverFirearm? Revolver { get; } +} \ No newline at end of file diff --git a/LabApi/Events/Arguments/Interfaces/Items/Firearms/IScp127ItemEvent.cs b/LabApi/Events/Arguments/Interfaces/Items/Firearms/IScp127ItemEvent.cs new file mode 100644 index 00000000..dd8652d7 --- /dev/null +++ b/LabApi/Events/Arguments/Interfaces/Items/Firearms/IScp127ItemEvent.cs @@ -0,0 +1,17 @@ +using LabApi.Features.Wrappers; + +namespace LabApi.Events.Arguments.Interfaces; + +/// +/// Represents an event that involves SCP-127. +/// +public interface IScp127ItemEvent : IItemEvent +{ + /// + Item? IItemEvent.Item => Scp127Item; + + /// + /// The SCP-127 item that is involved in the event. + /// + public Scp127Firearm? Scp127Item { get; } +} diff --git a/LabApi/Events/Arguments/Interfaces/Items/IJailbirdEvent.cs b/LabApi/Events/Arguments/Interfaces/Items/IJailbirdEvent.cs new file mode 100644 index 00000000..8684233c --- /dev/null +++ b/LabApi/Events/Arguments/Interfaces/Items/IJailbirdEvent.cs @@ -0,0 +1,17 @@ +using LabApi.Features.Wrappers; + +namespace LabApi.Events.Arguments.Interfaces.Items; + +/// +/// Represents an event that involves a jailbird item. +/// +public interface IJailbirdEvent : IItemEvent +{ + /// + Item? IItemEvent.Item => JailbirdItem; + + /// + /// The jailbird item that is involved in the event. + /// + public JailbirdItem? JailbirdItem { get; } +} diff --git a/LabApi/Events/Arguments/Interfaces/Items/IKeycardItemEvent.cs b/LabApi/Events/Arguments/Interfaces/Items/IKeycardItemEvent.cs new file mode 100644 index 00000000..2d3ebaae --- /dev/null +++ b/LabApi/Events/Arguments/Interfaces/Items/IKeycardItemEvent.cs @@ -0,0 +1,17 @@ +using LabApi.Features.Wrappers; + +namespace LabApi.Events.Arguments.Interfaces; + +/// +/// Represents an event that involves a keycard item. +/// +public interface IKeycardItemEvent : IItemEvent +{ + /// + Item? IItemEvent.Item => KeycardItem; + + /// + /// The keycard item that is involved in the event. + /// + public KeycardItem KeycardItem { get; } +} diff --git a/LabApi/Events/Arguments/ObjectiveEvents/EnemyKilledObjectiveEventArgs.cs b/LabApi/Events/Arguments/ObjectiveEvents/EnemyKilledObjectiveEventArgs.cs new file mode 100644 index 00000000..c69a4071 --- /dev/null +++ b/LabApi/Events/Arguments/ObjectiveEvents/EnemyKilledObjectiveEventArgs.cs @@ -0,0 +1,30 @@ +using LabApi.Features.Wrappers; +using PlayerRoles; + +namespace LabApi.Events.Arguments.ObjectiveEvents; + +/// +/// Represents the arguments for the event. +/// +public class EnemyKilledObjectiveEventArgs : ObjectiveCompletedBaseEventArgs +{ + /// + /// Initializes a new instance of the class. + /// + /// The player hub who triggered the objective. + /// The Faction to grant the influence to. + /// The influence points to grant to the . + /// The time to reduce from the . + /// Whether the objective completion has been sent to players. + /// The player that has been killed. + public EnemyKilledObjectiveEventArgs(ReferenceHub hub, Faction faction, float influenceToGrant, float timeToGrant, bool sendToPlayers, ReferenceHub targetHub) + : base(hub, faction, influenceToGrant, timeToGrant, sendToPlayers) + { + Target = Player.Get(targetHub); + } + + /// + /// Gets the player that has been killed. + /// + public Player Target { get; } +} diff --git a/LabApi/Events/Arguments/ObjectiveEvents/EnemyKillingObjectiveEventArgs.cs b/LabApi/Events/Arguments/ObjectiveEvents/EnemyKillingObjectiveEventArgs.cs new file mode 100644 index 00000000..d1b636ca --- /dev/null +++ b/LabApi/Events/Arguments/ObjectiveEvents/EnemyKillingObjectiveEventArgs.cs @@ -0,0 +1,30 @@ +using LabApi.Features.Wrappers; +using PlayerRoles; + +namespace LabApi.Events.Arguments.ObjectiveEvents; + +/// +/// Represents the arguments for the event. +/// +public class EnemyKillingObjectiveEventArgs : ObjectiveCompletingBaseEventArgs +{ + /// + /// Initializes a new instance of the class. + /// + /// The player hub who triggered the objective. + /// The Faction to grant the influence to. + /// The influence points to grant to the . + /// The time to reduce from the . + /// The player that has been killed. + /// Whether the objective completion will be sent to players. + public EnemyKillingObjectiveEventArgs(ReferenceHub hub, Faction faction, float influenceToGrant, float timeToGrant, ReferenceHub targetHub, bool sendToPlayers) + : base(hub, faction, influenceToGrant, timeToGrant, sendToPlayers) + { + Target = Player.Get(targetHub); + } + + /// + /// Gets the player that has been killed. + /// + public Player Target { get; } +} diff --git a/LabApi/Events/Arguments/ObjectiveEvents/EscapedObjectiveEventArgs.cs b/LabApi/Events/Arguments/ObjectiveEvents/EscapedObjectiveEventArgs.cs new file mode 100644 index 00000000..09deb136 --- /dev/null +++ b/LabApi/Events/Arguments/ObjectiveEvents/EscapedObjectiveEventArgs.cs @@ -0,0 +1,36 @@ +using PlayerRoles; + +namespace LabApi.Events.Arguments.ObjectiveEvents; + +/// +/// Represents the arguments for the event. +/// +public class EscapedObjectiveEventArgs : ObjectiveCompletedBaseEventArgs +{ + /// + /// Initializes a new instance of the class. + /// + /// The player hub who triggered the objective. + /// The Faction to grant the influence to. + /// The influence points to grant to the . + /// The time to reduce from the . + /// The new role the player gets after escaping. + /// Whether the objective completion has been sent to players. + /// The old role of the player. + public EscapedObjectiveEventArgs(ReferenceHub hub, Faction faction, float influenceToGrant, float timeToGrant, bool sendToPlayers, RoleTypeId oldRole, RoleTypeId newRole) + : base(hub, faction, influenceToGrant, timeToGrant, sendToPlayers) + { + OldRole = oldRole; + NewRole = newRole; + } + + /// + /// Gets the old role of the player. + /// + public RoleTypeId OldRole { get; } + + /// + /// Gets the new role the player is getting. + /// + public RoleTypeId NewRole { get; } +} diff --git a/LabApi/Events/Arguments/ObjectiveEvents/EscapingObjectiveEventArgs.cs b/LabApi/Events/Arguments/ObjectiveEvents/EscapingObjectiveEventArgs.cs new file mode 100644 index 00000000..245a7aae --- /dev/null +++ b/LabApi/Events/Arguments/ObjectiveEvents/EscapingObjectiveEventArgs.cs @@ -0,0 +1,36 @@ +using PlayerRoles; + +namespace LabApi.Events.Arguments.ObjectiveEvents; + +/// +/// Represents the arguments for the event. +/// +public class EscapingObjectiveEventArgs : ObjectiveCompletingBaseEventArgs +{ + /// + /// Initializes a new instance of the class. + /// + /// The player hub who triggered the objective. + /// The Faction to grant the influence to. + /// The influence points to grant to the . + /// The time to reduce from the . + /// The new role the player gets after escaping. + /// The old role of the player. + /// Whether the objective completion will be sent to players. + public EscapingObjectiveEventArgs(ReferenceHub hub, Faction faction, float influenceToGrant, float timeToGrant, RoleTypeId oldRole, RoleTypeId newRole, bool sendToPlayers) + : base(hub, faction, influenceToGrant, timeToGrant, sendToPlayers) + { + OldRole = oldRole; + NewRole = newRole; + } + + /// + /// Gets the old role of the player. + /// + public RoleTypeId OldRole { get; } + + /// + /// Gets the new role the player is getting. + /// + public RoleTypeId NewRole { get; } +} diff --git a/LabApi/Events/Arguments/ObjectiveEvents/GeneratorActivatedObjectiveEventArgs.cs b/LabApi/Events/Arguments/ObjectiveEvents/GeneratorActivatedObjectiveEventArgs.cs new file mode 100644 index 00000000..8cf18012 --- /dev/null +++ b/LabApi/Events/Arguments/ObjectiveEvents/GeneratorActivatedObjectiveEventArgs.cs @@ -0,0 +1,31 @@ +using LabApi.Features.Wrappers; +using MapGeneration.Distributors; +using PlayerRoles; + +namespace LabApi.Events.Arguments.ObjectiveEvents; + +/// +/// Represents the arguments for the event. +/// +public class GeneratorActivatedObjectiveEventArgs : ObjectiveCompletedBaseEventArgs +{ + /// + /// Initializes a new instance of the class. + /// + /// The player hub who triggered the objective. + /// The Faction to grant the influence to. + /// The influence points to grant to the . + /// The time to reduce from the . + /// Whether the objective completion has been sent to players. + /// The generator that has been activated. + public GeneratorActivatedObjectiveEventArgs(ReferenceHub hub, Faction faction, float influenceToGrant, float timeToGrant, bool sendToPlayers, Scp079Generator generator) + : base(hub, faction, influenceToGrant, timeToGrant, sendToPlayers) + { + Generator = Generator.Get(generator); + } + + /// + /// Gets the generator that has been activated. + /// + public Generator Generator { get; } +} \ No newline at end of file diff --git a/LabApi/Events/Arguments/ObjectiveEvents/GeneratorActivatingObjectiveEventArgs.cs b/LabApi/Events/Arguments/ObjectiveEvents/GeneratorActivatingObjectiveEventArgs.cs new file mode 100644 index 00000000..43bb7e5f --- /dev/null +++ b/LabApi/Events/Arguments/ObjectiveEvents/GeneratorActivatingObjectiveEventArgs.cs @@ -0,0 +1,31 @@ +using LabApi.Features.Wrappers; +using MapGeneration.Distributors; +using PlayerRoles; + +namespace LabApi.Events.Arguments.ObjectiveEvents; + +/// +/// Represents the arguments for the event. +/// +public class GeneratorActivatingObjectiveEventArgs : ObjectiveCompletingBaseEventArgs +{ + /// + /// Initializes a new instance of the class. + /// + /// The player hub who triggered the objective. + /// The Faction to grant the influence to. + /// The influence points to grant to the . + /// The time to reduce from the . + /// The generator that has been activated. + /// Whether the objective completion will be sent to players. + public GeneratorActivatingObjectiveEventArgs(ReferenceHub hub, Faction faction, float influenceToGrant, float timeToGrant, Scp079Generator generator, bool sendToPlayers) + : base(hub, faction, influenceToGrant, timeToGrant, sendToPlayers) + { + Generator = Generator.Get(generator); + } + + /// + /// Gets the generator that has been activated. + /// + public Generator Generator { get; } +} diff --git a/LabApi/Events/Arguments/ObjectiveEvents/ObjectiveCompletedBaseEventArgs.cs b/LabApi/Events/Arguments/ObjectiveEvents/ObjectiveCompletedBaseEventArgs.cs new file mode 100644 index 00000000..76113da9 --- /dev/null +++ b/LabApi/Events/Arguments/ObjectiveEvents/ObjectiveCompletedBaseEventArgs.cs @@ -0,0 +1,44 @@ +using LabApi.Events.Arguments.Interfaces; +using LabApi.Features.Wrappers; +using PlayerRoles; +using System; + +namespace LabApi.Events.Arguments.ObjectiveEvents; + +/// +/// Represents the arguments for the event. +/// +public class ObjectiveCompletedBaseEventArgs : EventArgs, IPlayerEvent, IObjectiveEvent +{ + /// + /// Initializes a new instance of the class. + /// + /// The player hub who triggered the objective. + /// The Faction to grant the influence to. + /// The influence points granted to the . + /// The time reduced from the . + /// Whether the objective completion has been sent to players. + public ObjectiveCompletedBaseEventArgs(ReferenceHub hub, Faction faction, float influenceToGrant, float timeToGrant, bool sendToPlayers) + { + Player = Player.Get(hub); + Faction = faction; + InfluenceToGrant = influenceToGrant; + TimeToGrant = timeToGrant; + SendToPlayers = sendToPlayers; + } + + /// + public Player Player { get; } + + /// + public Faction Faction { get; } + + /// + public float InfluenceToGrant { get; } + + /// + public float TimeToGrant { get; } + + /// + public bool SendToPlayers { get; } +} diff --git a/LabApi/Events/Arguments/ObjectiveEvents/ObjectiveCompletingBaseEventArgs.cs b/LabApi/Events/Arguments/ObjectiveEvents/ObjectiveCompletingBaseEventArgs.cs new file mode 100644 index 00000000..de9a335e --- /dev/null +++ b/LabApi/Events/Arguments/ObjectiveEvents/ObjectiveCompletingBaseEventArgs.cs @@ -0,0 +1,62 @@ +using LabApi.Events.Arguments.Interfaces; +using LabApi.Features.Wrappers; +using PlayerRoles; +using System; + +namespace LabApi.Events.Arguments.ObjectiveEvents; + +/// +/// Represents the arguments for the event. +/// +public abstract class ObjectiveCompletingBaseEventArgs : EventArgs, ICancellableEvent, IPlayerEvent, IObjectiveEvent +{ + /// + /// Initializes a new instance of the class. + /// + /// The player hub who triggered the objective. + /// The Faction to grant the influence to. + /// The influence points to grant to the . + /// The time to reduce from the . + /// Whether the objective completion will be sent to players. + public ObjectiveCompletingBaseEventArgs(ReferenceHub hub, Faction faction, float influenceToGrant, float timeToGrant, bool sendToPlayers) + { + Player = Player.Get(hub); + Faction = faction; + InfluenceToGrant = influenceToGrant; + TimeToGrant = timeToGrant; + SendToPlayers = sendToPlayers; + + IsAllowed = true; + } + + /// + /// Gets or sets the player who triggered the objective completion. + /// + public Player Player { get; set; } + + /// + /// Gets or sets the which receives the and rewards. + /// + public Faction Faction { get; set; } + + /// + /// Gets or sets the amount of influence granted to the . + /// + public float InfluenceToGrant { get; set; } + + /// + /// Gets or sets the amount of time reduced from the 's timer. + /// + /// + /// Negative values reduce the timer, positive extends it. + /// + public float TimeToGrant { get; set; } + + /// + /// Gets or sets whether the objective completion has been sent to players and is visible on their screen. + /// + public bool SendToPlayers { get; set; } + + /// + public bool IsAllowed { get; set; } +} diff --git a/LabApi/Events/Arguments/ObjectiveEvents/ScpDamagedObjectiveEventArgs.cs b/LabApi/Events/Arguments/ObjectiveEvents/ScpDamagedObjectiveEventArgs.cs new file mode 100644 index 00000000..a856bf50 --- /dev/null +++ b/LabApi/Events/Arguments/ObjectiveEvents/ScpDamagedObjectiveEventArgs.cs @@ -0,0 +1,30 @@ +using LabApi.Features.Wrappers; +using PlayerRoles; + +namespace LabApi.Events.Arguments.ObjectiveEvents; + +/// +/// Represents the arguments for the event. +/// +public class ScpDamagedObjectiveEventArgs : ObjectiveCompletedBaseEventArgs +{ + /// + /// Initializes a new instance of the class. + /// + /// The player hub who triggered the objective. + /// The Faction to grant the influence to. + /// The influence points to grant to the . + /// The time to reduce from the . + /// Whether the objective completion has been sent to players. + /// The hub of the player SCP that has been damaged. + public ScpDamagedObjectiveEventArgs(ReferenceHub hub, Faction faction, float influenceToGrant, float timeToGrant, bool sendToPlayers, ReferenceHub targetHub) + : base(hub, faction, influenceToGrant, timeToGrant, sendToPlayers) + { + Target = Player.Get(targetHub); + } + + /// + /// Gets the SCP player that has been damaged. + /// + public Player Target { get; } +} diff --git a/LabApi/Events/Arguments/ObjectiveEvents/ScpDamagingObjectiveEventArgs.cs b/LabApi/Events/Arguments/ObjectiveEvents/ScpDamagingObjectiveEventArgs.cs new file mode 100644 index 00000000..8a66f8a4 --- /dev/null +++ b/LabApi/Events/Arguments/ObjectiveEvents/ScpDamagingObjectiveEventArgs.cs @@ -0,0 +1,30 @@ +using LabApi.Features.Wrappers; +using PlayerRoles; + +namespace LabApi.Events.Arguments.ObjectiveEvents; + +/// +/// Represents the arguments for the event. +/// +public class ScpDamagingObjectiveEventArgs : ObjectiveCompletingBaseEventArgs +{ + /// + /// Initializes a new instance of the class. + /// + /// The player hub who triggered the objective. + /// The Faction to grant the influence to. + /// The influence points to grant to the . + /// The time to reduce from the . + /// The hub of the player SCP that has been damaged. + /// Whether the objective completion will be sent to players. + public ScpDamagingObjectiveEventArgs(ReferenceHub hub, Faction faction, float influenceToGrant, float timeToGrant, ReferenceHub targetHub, bool sendToPlayers) + : base(hub, faction, influenceToGrant, timeToGrant, sendToPlayers) + { + Target = Player.Get(targetHub); + } + + /// + /// Gets the SCP player that has been damaged. + /// + public Player Target { get; } +} diff --git a/LabApi/Events/Arguments/ObjectiveEvents/ScpItemPickedObjectiveEventArgs.cs b/LabApi/Events/Arguments/ObjectiveEvents/ScpItemPickedObjectiveEventArgs.cs new file mode 100644 index 00000000..b5ad603d --- /dev/null +++ b/LabApi/Events/Arguments/ObjectiveEvents/ScpItemPickedObjectiveEventArgs.cs @@ -0,0 +1,31 @@ +using InventorySystem.Items; +using LabApi.Features.Wrappers; +using PlayerRoles; + +namespace LabApi.Events.Arguments.ObjectiveEvents; + +/// +/// Represents the arguments for the event. +/// +public class ScpItemPickedObjectiveEventArgs : ObjectiveCompletedBaseEventArgs +{ + /// + /// Initializes a new instance of the class. + /// + /// The player hub who triggered the objective. + /// The Faction to grant the influence to. + /// The influence points to grant to the . + /// The time to reduce from the . + /// Whether the objective completion has been sent to players. + /// The item that has been picked up. + public ScpItemPickedObjectiveEventArgs(ReferenceHub hub, Faction faction, float influenceToGrant, float timeToGrant, bool sendToPlayers, ItemBase item) + : base(hub, faction, influenceToGrant, timeToGrant, sendToPlayers) + { + Item = Item.Get(item); + } + + /// + /// Gets the item that has been picked up. + /// + public Item Item { get; } +} diff --git a/LabApi/Events/Arguments/ObjectiveEvents/ScpItemPickingObjectiveEventArgs.cs b/LabApi/Events/Arguments/ObjectiveEvents/ScpItemPickingObjectiveEventArgs.cs new file mode 100644 index 00000000..e241b906 --- /dev/null +++ b/LabApi/Events/Arguments/ObjectiveEvents/ScpItemPickingObjectiveEventArgs.cs @@ -0,0 +1,31 @@ +using InventorySystem.Items; +using LabApi.Features.Wrappers; +using PlayerRoles; + +namespace LabApi.Events.Arguments.ObjectiveEvents; + +/// +/// Represents the arguments for the event. +/// +public class ScpItemPickingObjectiveEventArgs : ObjectiveCompletingBaseEventArgs +{ + /// + /// Initializes a new instance of the class. + /// + /// The player hub who triggered the objective. + /// The Faction to grant the influence to. + /// The influence points to grant to the . + /// The time to reduce from the . + /// The item that has been picked up. + /// Whether the objective completion will be sent to players. + public ScpItemPickingObjectiveEventArgs(ReferenceHub hub, Faction faction, float influenceToGrant, float timeToGrant, ItemBase item, bool sendToPlayers) + : base(hub, faction, influenceToGrant, timeToGrant, sendToPlayers) + { + Item = Item.Get(item); + } + + /// + /// Gets the item that has been picked up. + /// + public Item Item { get; } +} diff --git a/LabApi/Events/Arguments/PlayerEvents/PlayerActivatedGeneratorEventArgs.cs b/LabApi/Events/Arguments/PlayerEvents/PlayerActivatedGeneratorEventArgs.cs index bcc59650..9a63b0a8 100644 --- a/LabApi/Events/Arguments/PlayerEvents/PlayerActivatedGeneratorEventArgs.cs +++ b/LabApi/Events/Arguments/PlayerEvents/PlayerActivatedGeneratorEventArgs.cs @@ -13,11 +13,11 @@ public class PlayerActivatedGeneratorEventArgs : EventArgs, IPlayerEvent, IGener /// /// Initializes a new instance of the class. /// - /// The player who activated the generator. + /// The player who activated the generator. /// The generator that the player has activated. - public PlayerActivatedGeneratorEventArgs(ReferenceHub player, Scp079Generator generator) + public PlayerActivatedGeneratorEventArgs(ReferenceHub hub, Scp079Generator generator) { - Player = Player.Get(player); + Player = Player.Get(hub); Generator = Generator.Get(generator); } diff --git a/LabApi/Events/Arguments/PlayerEvents/PlayerActivatingGeneratorEventArgs.cs b/LabApi/Events/Arguments/PlayerEvents/PlayerActivatingGeneratorEventArgs.cs index def56887..691c1ae3 100644 --- a/LabApi/Events/Arguments/PlayerEvents/PlayerActivatingGeneratorEventArgs.cs +++ b/LabApi/Events/Arguments/PlayerEvents/PlayerActivatingGeneratorEventArgs.cs @@ -13,12 +13,12 @@ public class PlayerActivatingGeneratorEventArgs : EventArgs, IPlayerEvent, IGene /// /// Initializes a new instance of the class. /// - /// The player who is activating the generator. + /// The player who is activating the generator. /// The generator that the player is activating. - public PlayerActivatingGeneratorEventArgs(ReferenceHub player, Scp079Generator generator) + public PlayerActivatingGeneratorEventArgs(ReferenceHub hub, Scp079Generator generator) { IsAllowed = true; - Player = Player.Get(player); + Player = Player.Get(hub); Generator = Generator.Get(generator); } diff --git a/LabApi/Events/Arguments/PlayerEvents/PlayerAimedWeaponEventArgs.cs b/LabApi/Events/Arguments/PlayerEvents/PlayerAimedWeaponEventArgs.cs index a737ea84..0a797935 100644 --- a/LabApi/Events/Arguments/PlayerEvents/PlayerAimedWeaponEventArgs.cs +++ b/LabApi/Events/Arguments/PlayerEvents/PlayerAimedWeaponEventArgs.cs @@ -13,12 +13,12 @@ public class PlayerAimedWeaponEventArgs : EventArgs, IPlayerEvent, IFirearmItemE /// /// Initializes a new instance of the class. /// - /// The player who aimed the weapon. + /// The player who aimed the weapon. /// The weapon that the player aimed. /// Whether the player was aiming or unaiming their weapon. - public PlayerAimedWeaponEventArgs(ReferenceHub player, Firearm weapon, bool aiming) + public PlayerAimedWeaponEventArgs(ReferenceHub hub, Firearm weapon, bool aiming) { - Player = Player.Get(player); + Player = Player.Get(hub); FirearmItem = FirearmItem.Get(weapon); Aiming = aiming; } diff --git a/LabApi/Events/Arguments/PlayerEvents/PlayerAimingWeaponEventArgs.cs b/LabApi/Events/Arguments/PlayerEvents/PlayerAimingWeaponEventArgs.cs index 1bbf62cd..8d53a40c 100644 --- a/LabApi/Events/Arguments/PlayerEvents/PlayerAimingWeaponEventArgs.cs +++ b/LabApi/Events/Arguments/PlayerEvents/PlayerAimingWeaponEventArgs.cs @@ -6,25 +6,26 @@ namespace LabApi.Events.Arguments.PlayerEvents; +#pragma warning disable SA1005 // Single line comments should begin with single space // TODO: implement cancellable aiming. ///// ///// Represents the arguments for the event. ///// -//public class PlayerAimingWeaponEventArgs : EventArgs, IPlayerEvent, IWeaponEvent, ICancellableEvent -//{ -// /// -// /// Initializes a new instance of the class. -// /// -// /// The player who is aiming the weapon. -// /// The weapon that the player is aiming. -// /// Whether or not the player is aiming or unaiming their weapon. -// public PlayerAimingWeaponEventArgs(ReferenceHub player, ItemBase weapon, bool aiming) -// { -// IsAllowed = true; -// Player = Player.Get(player); -// Weapon = Item.Get(weapon); -// Aiming = aiming; -// } + //public class PlayerAimingWeaponEventArgs : EventArgs, IPlayerEvent, IWeaponEvent, ICancellableEvent + //{ + // /// + // /// Initializes a new instance of the class. + // /// + // /// The player who is aiming the weapon. + // /// The weapon that the player is aiming. + // /// Whether or not the player is aiming or unaiming their weapon. + // public PlayerAimingWeaponEventArgs(ReferenceHub player, ItemBase weapon, bool aiming) + // { + // IsAllowed = true; + // Player = Player.Get(player); + // Weapon = Item.Get(weapon); + // Aiming = aiming; + // } // /// // /// Gets the player who is aiming the weapon. @@ -41,4 +42,5 @@ namespace LabApi.Events.Arguments.PlayerEvents; // /// // public bool IsAllowed { get; set; } -//} \ No newline at end of file +//} +#pragma warning restore SA1005 // Single line comments should begin with single space \ No newline at end of file diff --git a/LabApi/Events/Arguments/PlayerEvents/PlayerBannedEventArgs.cs b/LabApi/Events/Arguments/PlayerEvents/PlayerBannedEventArgs.cs index 6731568d..e1e46d3f 100644 --- a/LabApi/Events/Arguments/PlayerEvents/PlayerBannedEventArgs.cs +++ b/LabApi/Events/Arguments/PlayerEvents/PlayerBannedEventArgs.cs @@ -12,14 +12,14 @@ public class PlayerBannedEventArgs : EventArgs, IPlayerEvent /// /// Initializes a new instance of the class. /// - /// The player who is getting the ban. + /// The player who is getting the ban. /// The ID of the player who is getting the ban. /// The player who issued the ban. /// The reason of the ban. /// The duration of the ban. - public PlayerBannedEventArgs(ReferenceHub? player, string playerId, ReferenceHub issuer, string reason, long duration) + public PlayerBannedEventArgs(ReferenceHub? hub, string playerId, ReferenceHub issuer, string reason, long duration) { - Player = Player.Get(player); + Player = Player.Get(hub); PlayerId = playerId; Issuer = Player.Get(issuer); Reason = reason; diff --git a/LabApi/Events/Arguments/PlayerEvents/PlayerBanningEventArgs.cs b/LabApi/Events/Arguments/PlayerEvents/PlayerBanningEventArgs.cs index 4358f492..f0c74e4f 100644 --- a/LabApi/Events/Arguments/PlayerEvents/PlayerBanningEventArgs.cs +++ b/LabApi/Events/Arguments/PlayerEvents/PlayerBanningEventArgs.cs @@ -12,15 +12,15 @@ public class PlayerBanningEventArgs : EventArgs, IPlayerEvent, ICancellableEvent /// /// Initializes a new instance of the class. /// - /// The player who is getting the ban. + /// The player who is getting the ban. /// The ID of the player who is getting the ban. /// The player who issued the ban. /// The reason of the ban. /// The duration of the ban. - public PlayerBanningEventArgs(ReferenceHub? player, string playerId, ReferenceHub issuer, string reason, long duration) + public PlayerBanningEventArgs(ReferenceHub? hub, string playerId, ReferenceHub issuer, string reason, long duration) { IsAllowed = true; - Player = Player.Get(player); + Player = Player.Get(hub); PlayerId = playerId; Issuer = Player.Get(issuer); Reason = reason; @@ -31,7 +31,7 @@ public PlayerBanningEventArgs(ReferenceHub? player, string playerId, ReferenceHu /// Gets the player who is being banned. /// public Player? Player { get; } - + /// /// Gets the ID of the player who is being banned. /// diff --git a/LabApi/Events/Arguments/PlayerEvents/PlayerCancelledUsingItemEventArgs.cs b/LabApi/Events/Arguments/PlayerEvents/PlayerCancelledUsingItemEventArgs.cs index ec2b16bd..751c18b2 100644 --- a/LabApi/Events/Arguments/PlayerEvents/PlayerCancelledUsingItemEventArgs.cs +++ b/LabApi/Events/Arguments/PlayerEvents/PlayerCancelledUsingItemEventArgs.cs @@ -8,16 +8,16 @@ namespace LabApi.Events.Arguments.PlayerEvents; /// /// Represents the arguments for the event. /// -public class PlayerCancelledUsingItemEventArgs : EventArgs, IUsableItemEvent +public class PlayerCancelledUsingItemEventArgs : EventArgs, IUsableItemEvent, IPlayerEvent { /// /// Initializes a new instance of the class. /// - /// The player who cancelled using the item. + /// The player who cancelled using the item. /// The item which the player cancelled using. - public PlayerCancelledUsingItemEventArgs(ReferenceHub player, BaseUsableItem item) + public PlayerCancelledUsingItemEventArgs(ReferenceHub hub, BaseUsableItem item) { - Player = Player.Get(player); + Player = Player.Get(hub); UsableItem = UsableItem.Get(item); } diff --git a/LabApi/Events/Arguments/PlayerEvents/PlayerCancellingUsingItemEventArgs.cs b/LabApi/Events/Arguments/PlayerEvents/PlayerCancellingUsingItemEventArgs.cs index 60c16c64..fdbc61d1 100644 --- a/LabApi/Events/Arguments/PlayerEvents/PlayerCancellingUsingItemEventArgs.cs +++ b/LabApi/Events/Arguments/PlayerEvents/PlayerCancellingUsingItemEventArgs.cs @@ -8,17 +8,17 @@ namespace LabApi.Events.Arguments.PlayerEvents; /// /// Represents the arguments for the event. /// -public class PlayerCancellingUsingItemEventArgs : EventArgs, IUsableItemEvent, ICancellableEvent +public class PlayerCancellingUsingItemEventArgs : EventArgs, IUsableItemEvent, ICancellableEvent, IPlayerEvent { /// /// Initializes a new instance of the class. /// - /// The player who is cancelling using the item. + /// The player who is cancelling using the item. /// The item which the player cancels using. - public PlayerCancellingUsingItemEventArgs(ReferenceHub player, BaseUsableItem item) + public PlayerCancellingUsingItemEventArgs(ReferenceHub hub, BaseUsableItem item) { IsAllowed = true; - Player = Player.Get(player); + Player = Player.Get(hub); UsableItem = UsableItem.Get(item); } diff --git a/LabApi/Events/Arguments/PlayerEvents/PlayerChangedAttachmentsEventArgs.cs b/LabApi/Events/Arguments/PlayerEvents/PlayerChangedAttachmentsEventArgs.cs new file mode 100644 index 00000000..32304ec7 --- /dev/null +++ b/LabApi/Events/Arguments/PlayerEvents/PlayerChangedAttachmentsEventArgs.cs @@ -0,0 +1,43 @@ +using InventorySystem.Items.Firearms; +using LabApi.Events.Arguments.Interfaces; +using LabApi.Features.Wrappers; +using System; + +namespace LabApi.Events.Arguments.PlayerEvents; + +/// +/// Represents the arguments for the event. +/// +public class PlayerChangedAttachmentsEventArgs : EventArgs, IPlayerEvent, IFirearmItemEvent +{ + /// + /// Initialized a new instance of . + /// + /// The player who is changing the firearm attachments. + /// The firearm whose attachments are being changed. + /// The old attachments code. + /// The new attachments code. + public PlayerChangedAttachmentsEventArgs(ReferenceHub player, Firearm firearm, uint oldAttachments, uint newAttachments) + { + Player = Player.Get(player); + FirearmItem = FirearmItem.Get(firearm); + OldAttachments = oldAttachments; + NewAttachments = newAttachments; + } + + /// + public Player Player { get; } + + /// + public FirearmItem FirearmItem { get; } + + /// + /// Gets previous attachments code. + /// + public uint OldAttachments { get; } + + /// + /// Gets the new attachments code. + /// + public uint NewAttachments { get; } +} diff --git a/LabApi/Events/Arguments/PlayerEvents/PlayerChangedBadgeVisibilityEventArgs.cs b/LabApi/Events/Arguments/PlayerEvents/PlayerChangedBadgeVisibilityEventArgs.cs new file mode 100644 index 00000000..e472ef42 --- /dev/null +++ b/LabApi/Events/Arguments/PlayerEvents/PlayerChangedBadgeVisibilityEventArgs.cs @@ -0,0 +1,39 @@ +using LabApi.Events.Arguments.Interfaces; +using LabApi.Features.Wrappers; +using System; + +namespace LabApi.Events.Arguments.PlayerEvents; + +/// +/// Represents the arguments for the event. +/// +public class PlayerChangedBadgeVisibilityEventArgs : EventArgs, IPlayerEvent +{ + /// + /// Initializes a new instance of the class. + /// + /// The component of the player that changed their badge visibility. + /// Whether the badge is a global badge. + /// The new visibility state. + public PlayerChangedBadgeVisibilityEventArgs(ReferenceHub hub, bool isGlobal, bool newVisibility) + { + Player = Player.Get(hub); + IsGlobalBadge = isGlobal; + NewVisibility = newVisibility; + } + + /// + /// The player that changed their badge visibility. + /// + public Player Player { get; } + + /// + /// if the badge is a global badge, otherwise it is a local badge. + /// + public bool IsGlobalBadge { get; } + + /// + /// Whether the badge is now visible. + /// + public bool NewVisibility { get; } +} diff --git a/LabApi/Events/Arguments/PlayerEvents/PlayerChangedItemEventArgs.cs b/LabApi/Events/Arguments/PlayerEvents/PlayerChangedItemEventArgs.cs index 7333606b..2b34bcdf 100644 --- a/LabApi/Events/Arguments/PlayerEvents/PlayerChangedItemEventArgs.cs +++ b/LabApi/Events/Arguments/PlayerEvents/PlayerChangedItemEventArgs.cs @@ -13,12 +13,12 @@ public class PlayerChangedItemEventArgs : EventArgs, IPlayerEvent /// /// Initializes a new instance of the class. /// - /// The player who changed current item. + /// The player who changed current item. /// The old item which player changed to. /// The new item which player changed to. - public PlayerChangedItemEventArgs(ReferenceHub player, ItemBase? oldItem, ItemBase? newItem) + public PlayerChangedItemEventArgs(ReferenceHub hub, ItemBase? oldItem, ItemBase? newItem) { - Player = Player.Get(player); + Player = Player.Get(hub); OldItem = Item.Get(oldItem); NewItem = Item.Get(newItem); } diff --git a/LabApi/Events/Arguments/PlayerEvents/PlayerChangedNicknameEventArgs.cs b/LabApi/Events/Arguments/PlayerEvents/PlayerChangedNicknameEventArgs.cs index f3368fe2..adf3fd81 100644 --- a/LabApi/Events/Arguments/PlayerEvents/PlayerChangedNicknameEventArgs.cs +++ b/LabApi/Events/Arguments/PlayerEvents/PlayerChangedNicknameEventArgs.cs @@ -12,12 +12,12 @@ public class PlayerChangedNicknameEventArgs : EventArgs, IPlayerEvent /// /// Initializes a new instance of the class. /// - /// The player whose nickname has changed. + /// The player whose nickname has changed. /// The old nickname of the player. /// The new nickname of the player. - public PlayerChangedNicknameEventArgs(ReferenceHub player, string? oldNickname, string? newNickname) + public PlayerChangedNicknameEventArgs(ReferenceHub hub, string? oldNickname, string? newNickname) { - Player = Player.Get(player); + Player = Player.Get(hub); OldNickname = oldNickname; NewNickname = newNickname; } diff --git a/LabApi/Events/Arguments/PlayerEvents/PlayerChangedRadioRangeEventArgs.cs b/LabApi/Events/Arguments/PlayerEvents/PlayerChangedRadioRangeEventArgs.cs index 92984e5b..59978c05 100644 --- a/LabApi/Events/Arguments/PlayerEvents/PlayerChangedRadioRangeEventArgs.cs +++ b/LabApi/Events/Arguments/PlayerEvents/PlayerChangedRadioRangeEventArgs.cs @@ -9,17 +9,17 @@ namespace LabApi.Events.Arguments.PlayerEvents; /// /// Represents the arguments for the event. /// -public class PlayerChangedRadioRangeEventArgs : EventArgs, IRadioItemEvent +public class PlayerChangedRadioRangeEventArgs : EventArgs, IRadioItemEvent, IPlayerEvent { /// /// Initializes a new instance of the class. /// - /// The player who changed radio range. + /// The player who changed radio range. /// The radio item. /// The new range level. - public PlayerChangedRadioRangeEventArgs(ReferenceHub player, BaseRadioItem radio, RadioRangeLevel range) + public PlayerChangedRadioRangeEventArgs(ReferenceHub hub, BaseRadioItem radio, RadioRangeLevel range) { - Player = Player.Get(player); + Player = Player.Get(hub); RadioItem = RadioItem.Get(radio); Range = range; } diff --git a/LabApi/Events/Arguments/PlayerEvents/PlayerChangedRoleEventArgs.cs b/LabApi/Events/Arguments/PlayerEvents/PlayerChangedRoleEventArgs.cs index fcd19bae..a2fc0810 100644 --- a/LabApi/Events/Arguments/PlayerEvents/PlayerChangedRoleEventArgs.cs +++ b/LabApi/Events/Arguments/PlayerEvents/PlayerChangedRoleEventArgs.cs @@ -13,14 +13,14 @@ public class PlayerChangedRoleEventArgs : EventArgs, IPlayerEvent /// /// Initializes a new instance of the class. /// - /// The player whose role changed. + /// The player whose role changed. /// The old role type. /// The new role object of the player. /// The reason of role changed. /// The spawn flags used for this role change. - public PlayerChangedRoleEventArgs(ReferenceHub player, RoleTypeId oldRole, PlayerRoleBase newRole, RoleChangeReason changeReason, RoleSpawnFlags spawnFlags) + public PlayerChangedRoleEventArgs(ReferenceHub hub, RoleTypeId oldRole, PlayerRoleBase newRole, RoleChangeReason changeReason, RoleSpawnFlags spawnFlags) { - Player = Player.Get(player); + Player = Player.Get(hub); OldRole = oldRole; NewRole = newRole; ChangeReason = changeReason; diff --git a/LabApi/Events/Arguments/PlayerEvents/PlayerChangedSpectatorEventArgs.cs b/LabApi/Events/Arguments/PlayerEvents/PlayerChangedSpectatorEventArgs.cs index ae76eab5..69a6cf48 100644 --- a/LabApi/Events/Arguments/PlayerEvents/PlayerChangedSpectatorEventArgs.cs +++ b/LabApi/Events/Arguments/PlayerEvents/PlayerChangedSpectatorEventArgs.cs @@ -12,12 +12,12 @@ public class PlayerChangedSpectatorEventArgs : EventArgs, IPlayerEvent /// /// Initializes a new instance of the class. /// - /// The player who changed spectator. + /// The player who changed spectator. /// Old target that was spectated previously. /// New target that was spectating changed to. - public PlayerChangedSpectatorEventArgs(ReferenceHub player, ReferenceHub oldTarget, ReferenceHub newTarget) + public PlayerChangedSpectatorEventArgs(ReferenceHub hub, ReferenceHub oldTarget, ReferenceHub newTarget) { - Player = Player.Get(player); + Player = Player.Get(hub); OldTarget = Player.Get(oldTarget); NewTarget = Player.Get(newTarget); } diff --git a/LabApi/Events/Arguments/PlayerEvents/PlayerChangingAttachmentsEventArgs.cs b/LabApi/Events/Arguments/PlayerEvents/PlayerChangingAttachmentsEventArgs.cs new file mode 100644 index 00000000..669ff328 --- /dev/null +++ b/LabApi/Events/Arguments/PlayerEvents/PlayerChangingAttachmentsEventArgs.cs @@ -0,0 +1,47 @@ +using InventorySystem.Items.Firearms; +using LabApi.Events.Arguments.Interfaces; +using LabApi.Features.Wrappers; +using System; + +namespace LabApi.Events.Arguments.PlayerEvents; + +/// +/// Represents the arguments for the event. +/// +public class PlayerChangingAttachmentsEventArgs : EventArgs, IPlayerEvent, IFirearmItemEvent, ICancellableEvent +{ + /// + /// Initialized a new instance of . + /// + /// The player who is changing the firearm attachments. + /// The firearm whose attachments are being changed. + /// The old attachments code. + /// The new attachments code requested by the player. + public PlayerChangingAttachmentsEventArgs(ReferenceHub player, Firearm firearm, uint oldAttachments, uint newAttachments) + { + Player = Player.Get(player); + FirearmItem = FirearmItem.Get(firearm); + OldAttachments = oldAttachments; + NewAttachments = newAttachments; + IsAllowed = true; + } + + /// + public Player Player { get; } + + /// + public FirearmItem FirearmItem { get; } + + /// + /// Gets previous attachments code. + /// + public uint OldAttachments { get; } + + /// + /// Gets or sets new attachments code. + /// + public uint NewAttachments { get; set; } + + /// + public bool IsAllowed { get; set; } +} diff --git a/LabApi/Events/Arguments/PlayerEvents/PlayerChangingBadgeVisibilityEventArgs.cs b/LabApi/Events/Arguments/PlayerEvents/PlayerChangingBadgeVisibilityEventArgs.cs new file mode 100644 index 00000000..6fb7ee1e --- /dev/null +++ b/LabApi/Events/Arguments/PlayerEvents/PlayerChangingBadgeVisibilityEventArgs.cs @@ -0,0 +1,43 @@ +using LabApi.Events.Arguments.Interfaces; +using LabApi.Features.Wrappers; +using System; + +namespace LabApi.Events.Arguments.PlayerEvents; + +/// +/// Represents the arguments for the event. +/// +public class PlayerChangingBadgeVisibilityEventArgs : EventArgs, IPlayerEvent, ICancellableEvent +{ + /// + /// Initializes a new instance of the class. + /// + /// The component of the player that is changing their badge visibility. + /// Whether the badge is a global badge. + /// The new visibility state. + public PlayerChangingBadgeVisibilityEventArgs(ReferenceHub hub, bool isGlobal, bool newVisibility) + { + Player = Player.Get(hub); + IsGlobalBadge = isGlobal; + NewVisibility = newVisibility; + IsAllowed = true; + } + + /// + /// The player that is changing their badge visibility. + /// + public Player Player { get; } + + /// + /// if the badge is a global badge, otherwise it is a local badge. + /// + public bool IsGlobalBadge { get; } + + /// + /// Whether the badge will be visible. + /// + public bool NewVisibility { get; } + + /// + public bool IsAllowed { get; set; } +} diff --git a/LabApi/Events/Arguments/PlayerEvents/PlayerChangingItemEventArgs.cs b/LabApi/Events/Arguments/PlayerEvents/PlayerChangingItemEventArgs.cs index cbfe21e8..1f3e719f 100644 --- a/LabApi/Events/Arguments/PlayerEvents/PlayerChangingItemEventArgs.cs +++ b/LabApi/Events/Arguments/PlayerEvents/PlayerChangingItemEventArgs.cs @@ -13,13 +13,13 @@ public class PlayerChangingItemEventArgs : EventArgs, IPlayerEvent, ICancellable /// /// Initializes a new instance of the class. /// - /// The player who is changing item. + /// The player who is changing item. /// The old item. /// The new item that is being equipped. - public PlayerChangingItemEventArgs(ReferenceHub player, ItemBase? oldItem, ItemBase? newItem) + public PlayerChangingItemEventArgs(ReferenceHub hub, ItemBase? oldItem, ItemBase? newItem) { IsAllowed = true; - Player = Player.Get(player); + Player = Player.Get(hub); OldItem = Item.Get(oldItem); NewItem = Item.Get(newItem); } diff --git a/LabApi/Events/Arguments/PlayerEvents/PlayerChangingNicknameEventArgs.cs b/LabApi/Events/Arguments/PlayerEvents/PlayerChangingNicknameEventArgs.cs index 12a45c24..159b66bd 100644 --- a/LabApi/Events/Arguments/PlayerEvents/PlayerChangingNicknameEventArgs.cs +++ b/LabApi/Events/Arguments/PlayerEvents/PlayerChangingNicknameEventArgs.cs @@ -12,13 +12,13 @@ public class PlayerChangingNicknameEventArgs : EventArgs, IPlayerEvent, ICancell /// /// Initializes a new instance of the class. /// - /// The player whose nickname is changing. + /// The player whose nickname is changing. /// The old nickname of the player. /// The new nickname of the player. - public PlayerChangingNicknameEventArgs(ReferenceHub player, string? oldNickname, string? newNickname) + public PlayerChangingNicknameEventArgs(ReferenceHub hub, string? oldNickname, string? newNickname) { IsAllowed = true; - Player = Player.Get(player); + Player = Player.Get(hub); OldNickname = oldNickname; NewNickname = newNickname; } @@ -33,7 +33,7 @@ public PlayerChangingNicknameEventArgs(ReferenceHub player, string? oldNickname, /// /// Null means they did not have a custom display-name before. public string? OldNickname { get; } - + /// /// Gets or sets the new nickname of the player. /// diff --git a/LabApi/Events/Arguments/PlayerEvents/PlayerChangingRadioRangeEventArgs.cs b/LabApi/Events/Arguments/PlayerEvents/PlayerChangingRadioRangeEventArgs.cs index 0f79bfc5..d1a848c3 100644 --- a/LabApi/Events/Arguments/PlayerEvents/PlayerChangingRadioRangeEventArgs.cs +++ b/LabApi/Events/Arguments/PlayerEvents/PlayerChangingRadioRangeEventArgs.cs @@ -9,18 +9,18 @@ namespace LabApi.Events.Arguments.PlayerEvents; /// /// Represents the arguments for the event. /// -public class PlayerChangingRadioRangeEventArgs : EventArgs, IRadioItemEvent, ICancellableEvent +public class PlayerChangingRadioRangeEventArgs : EventArgs, IRadioItemEvent, ICancellableEvent, IPlayerEvent { /// /// Initializes a new instance of the class. /// - /// The player who is changing radio range. + /// The player who is changing radio range. /// The radio item. /// The range level that is radio being changed to. - public PlayerChangingRadioRangeEventArgs(ReferenceHub player, BaseRadioItem radio, RadioRangeLevel range) + public PlayerChangingRadioRangeEventArgs(ReferenceHub hub, BaseRadioItem radio, RadioRangeLevel range) { IsAllowed = true; - Player = Player.Get(player); + Player = Player.Get(hub); RadioItem = RadioItem.Get(radio); Range = range; } diff --git a/LabApi/Events/Arguments/PlayerEvents/PlayerChangingRoleEventArgs.cs b/LabApi/Events/Arguments/PlayerEvents/PlayerChangingRoleEventArgs.cs index 0ce9e283..59c68293 100644 --- a/LabApi/Events/Arguments/PlayerEvents/PlayerChangingRoleEventArgs.cs +++ b/LabApi/Events/Arguments/PlayerEvents/PlayerChangingRoleEventArgs.cs @@ -13,15 +13,15 @@ public class PlayerChangingRoleEventArgs : EventArgs, IPlayerEvent, ICancellable /// /// Initializes a new instance of the class. /// - /// The player whose role is changing. + /// The player whose role is changing. /// The old role object of the player. /// The new role type. /// The reason of role changing. /// The spawn flags for this role change. - public PlayerChangingRoleEventArgs(ReferenceHub player, PlayerRoleBase oldRole, RoleTypeId newRole, RoleChangeReason changeReason, RoleSpawnFlags spawnFlags) + public PlayerChangingRoleEventArgs(ReferenceHub hub, PlayerRoleBase oldRole, RoleTypeId newRole, RoleChangeReason changeReason, RoleSpawnFlags spawnFlags) { IsAllowed = true; - Player = Player.Get(player); + Player = Player.Get(hub); OldRole = oldRole; NewRole = newRole; ChangeReason = changeReason; diff --git a/LabApi/Events/Arguments/PlayerEvents/PlayerCheckedHitmarkerEventArgs.cs b/LabApi/Events/Arguments/PlayerEvents/PlayerCheckedHitmarkerEventArgs.cs new file mode 100644 index 00000000..9291f616 --- /dev/null +++ b/LabApi/Events/Arguments/PlayerEvents/PlayerCheckedHitmarkerEventArgs.cs @@ -0,0 +1,47 @@ +using LabApi.Events.Arguments.Interfaces; +using LabApi.Features.Wrappers; +using PlayerStatsSystem; +using System; + +namespace LabApi.Events.Arguments.PlayerEvents; + +/// +/// Represents the arguments for the event. +/// +public class PlayerCheckedHitmarkerEventArgs : EventArgs, IPlayerEvent +{ + /// + /// Initializes a new instance for the class. + /// + /// The player that hitmarker should send. + /// The damage dealt to the . + /// The player who got hurt by . + /// The result of the check. + public PlayerCheckedHitmarkerEventArgs(ReferenceHub hub, AttackerDamageHandler adh, ReferenceHub victim, bool result) + { + Player = Player.Get(hub); + DamageHandler = adh; + Victim = Player.Get(victim); + Result = result; + } + + /// + /// Gets the player that the hitmarker is being sent to. + /// + public Player Player { get; } + + /// + /// Gets the player that was hit. + /// + public Player Victim { get; } + + /// + /// Gets the damage handler. + /// + public AttackerDamageHandler DamageHandler { get; } + + /// + /// Gets the check result. + /// + public bool Result { get; } +} diff --git a/LabApi/Events/Arguments/PlayerEvents/PlayerClosedGeneratorEventArgs.cs b/LabApi/Events/Arguments/PlayerEvents/PlayerClosedGeneratorEventArgs.cs index bc30549e..ccfa2033 100644 --- a/LabApi/Events/Arguments/PlayerEvents/PlayerClosedGeneratorEventArgs.cs +++ b/LabApi/Events/Arguments/PlayerEvents/PlayerClosedGeneratorEventArgs.cs @@ -13,11 +13,11 @@ public class PlayerClosedGeneratorEventArgs : EventArgs, IPlayerEvent, IGenerato /// /// Initializes a new instance of the class. /// - /// The player who closed the generator. + /// The player who closed the generator. /// The generator. - public PlayerClosedGeneratorEventArgs(ReferenceHub player, Scp079Generator generator) + public PlayerClosedGeneratorEventArgs(ReferenceHub hub, Scp079Generator generator) { - Player = Player.Get(player); + Player = Player.Get(hub); Generator = Generator.Get(generator); } diff --git a/LabApi/Events/Arguments/PlayerEvents/PlayerClosingGeneratorEventArgs.cs b/LabApi/Events/Arguments/PlayerEvents/PlayerClosingGeneratorEventArgs.cs index 4acb3bde..8ae7bbc2 100644 --- a/LabApi/Events/Arguments/PlayerEvents/PlayerClosingGeneratorEventArgs.cs +++ b/LabApi/Events/Arguments/PlayerEvents/PlayerClosingGeneratorEventArgs.cs @@ -13,12 +13,12 @@ public class PlayerClosingGeneratorEventArgs : EventArgs, IPlayerEvent, IGenerat /// /// Initializes a new instance of the class. /// - /// The player who is closing the generator. + /// The player who is closing the generator. /// The generator. - public PlayerClosingGeneratorEventArgs(ReferenceHub player, Scp079Generator generator) + public PlayerClosingGeneratorEventArgs(ReferenceHub hub, Scp079Generator generator) { IsAllowed = true; - Player = Player.Get(player); + Player = Player.Get(hub); Generator = Generator.Get(generator); } diff --git a/LabApi/Events/Arguments/PlayerEvents/PlayerCuffedEventArgs.cs b/LabApi/Events/Arguments/PlayerEvents/PlayerCuffedEventArgs.cs index 1b7c6076..7abc3d10 100644 --- a/LabApi/Events/Arguments/PlayerEvents/PlayerCuffedEventArgs.cs +++ b/LabApi/Events/Arguments/PlayerEvents/PlayerCuffedEventArgs.cs @@ -12,11 +12,11 @@ public class PlayerCuffedEventArgs : EventArgs, IPlayerEvent, ITargetEvent /// /// Initializes a new instance of the class. /// - /// The player who detained another one. + /// The player who detained another one. /// The player who was detained. - public PlayerCuffedEventArgs(ReferenceHub player, ReferenceHub target) + public PlayerCuffedEventArgs(ReferenceHub hub, ReferenceHub target) { - Player = Player.Get(player); + Player = Player.Get(hub); Target = Player.Get(target); } diff --git a/LabApi/Events/Arguments/PlayerEvents/PlayerCuffingEventArgs.cs b/LabApi/Events/Arguments/PlayerEvents/PlayerCuffingEventArgs.cs index 4aafad95..16b0e9c6 100644 --- a/LabApi/Events/Arguments/PlayerEvents/PlayerCuffingEventArgs.cs +++ b/LabApi/Events/Arguments/PlayerEvents/PlayerCuffingEventArgs.cs @@ -12,12 +12,12 @@ public class PlayerCuffingEventArgs : EventArgs, IPlayerEvent, ITargetEvent, ICa /// /// Initializes a new instance of the class. /// - /// The player who is detaining another one. + /// The player who is detaining another one. /// The player who is being detained. - public PlayerCuffingEventArgs(ReferenceHub player, ReferenceHub target) + public PlayerCuffingEventArgs(ReferenceHub hub, ReferenceHub target) { IsAllowed = true; - Player = Player.Get(player); + Player = Player.Get(hub); Target = Player.Get(target); } diff --git a/LabApi/Events/Arguments/PlayerEvents/PlayerDamagedShootingTargetEventArgs.cs b/LabApi/Events/Arguments/PlayerEvents/PlayerDamagedShootingTargetEventArgs.cs index cf0010f7..a2a6c88d 100644 --- a/LabApi/Events/Arguments/PlayerEvents/PlayerDamagedShootingTargetEventArgs.cs +++ b/LabApi/Events/Arguments/PlayerEvents/PlayerDamagedShootingTargetEventArgs.cs @@ -14,12 +14,12 @@ public class PlayerDamagedShootingTargetEventArgs : EventArgs, IPlayerEvent, ISh /// /// Initializes a new instance of the class. /// - /// The player who damaged the shooting target. + /// The player who damaged the shooting target. /// The shooting target. /// The damage handler. - public PlayerDamagedShootingTargetEventArgs(ReferenceHub player, ShootingTarget target, DamageHandlerBase damageHandler) + public PlayerDamagedShootingTargetEventArgs(ReferenceHub hub, ShootingTarget target, DamageHandlerBase damageHandler) { - Player = Player.Get(player); + Player = Player.Get(hub); ShootingTarget = ShootingTargetToy.Get(target); DamageHandler = damageHandler; } diff --git a/LabApi/Events/Arguments/PlayerEvents/PlayerDamagedWindowEventArgs.cs b/LabApi/Events/Arguments/PlayerEvents/PlayerDamagedWindowEventArgs.cs index 2a67d768..b13308cb 100644 --- a/LabApi/Events/Arguments/PlayerEvents/PlayerDamagedWindowEventArgs.cs +++ b/LabApi/Events/Arguments/PlayerEvents/PlayerDamagedWindowEventArgs.cs @@ -13,12 +13,12 @@ public class PlayerDamagedWindowEventArgs : EventArgs, IPlayerEvent /// /// Initializes a new instance of the class. /// - /// The player who damaged the window. + /// The player who damaged the window. /// The window. /// The damage handler. - public PlayerDamagedWindowEventArgs(ReferenceHub player, BreakableWindow window, DamageHandlerBase damageHandler) + public PlayerDamagedWindowEventArgs(ReferenceHub hub, BreakableWindow window, DamageHandlerBase damageHandler) { - Player = Player.Get(player); + Player = Player.Get(hub); Window = window; DamageHandler = damageHandler; } diff --git a/LabApi/Events/Arguments/PlayerEvents/PlayerDamagingShootingTargetEventArgs.cs b/LabApi/Events/Arguments/PlayerEvents/PlayerDamagingShootingTargetEventArgs.cs index 1a25a160..602e94e6 100644 --- a/LabApi/Events/Arguments/PlayerEvents/PlayerDamagingShootingTargetEventArgs.cs +++ b/LabApi/Events/Arguments/PlayerEvents/PlayerDamagingShootingTargetEventArgs.cs @@ -14,13 +14,13 @@ public class PlayerDamagingShootingTargetEventArgs : EventArgs, IPlayerEvent, IS /// /// Initializes a new instance of the class. /// - /// The player who is damaging the shooting target. + /// The player who is damaging the shooting target. /// The shooting target. /// The damage handler. - public PlayerDamagingShootingTargetEventArgs(ReferenceHub player, ShootingTarget target, DamageHandlerBase damageHandler) + public PlayerDamagingShootingTargetEventArgs(ReferenceHub hub, ShootingTarget target, DamageHandlerBase damageHandler) { IsAllowed = true; - Player = Player.Get(player); + Player = Player.Get(hub); ShootingTarget = ShootingTargetToy.Get(target); DamageHandler = damageHandler; } diff --git a/LabApi/Events/Arguments/PlayerEvents/PlayerDamagingWindowEventArgs.cs b/LabApi/Events/Arguments/PlayerEvents/PlayerDamagingWindowEventArgs.cs index 3758606e..a25afb44 100644 --- a/LabApi/Events/Arguments/PlayerEvents/PlayerDamagingWindowEventArgs.cs +++ b/LabApi/Events/Arguments/PlayerEvents/PlayerDamagingWindowEventArgs.cs @@ -8,18 +8,18 @@ namespace LabApi.Events.Arguments.PlayerEvents; /// /// Represents the arguments for the event. /// -public class PlayerDamagingWindowEventArgs : EventArgs, ICancellableEvent +public class PlayerDamagingWindowEventArgs : EventArgs, ICancellableEvent, IPlayerEvent { /// /// Initializes a new instance of the class. /// - /// The player who is damaging the window. + /// The player who is damaging the window. /// The window. /// The damage handler. - public PlayerDamagingWindowEventArgs(ReferenceHub player, BreakableWindow window, DamageHandlerBase damageHandler) + public PlayerDamagingWindowEventArgs(ReferenceHub hub, BreakableWindow window, DamageHandlerBase damageHandler) { IsAllowed = true; - Player = Player.Get(player); + Player = Player.Get(hub); Window = window; DamageHandler = damageHandler; } diff --git a/LabApi/Events/Arguments/PlayerEvents/PlayerDeactivatedGeneratorEventArgs.cs b/LabApi/Events/Arguments/PlayerEvents/PlayerDeactivatedGeneratorEventArgs.cs index 8fd753a4..dcfdee83 100644 --- a/LabApi/Events/Arguments/PlayerEvents/PlayerDeactivatedGeneratorEventArgs.cs +++ b/LabApi/Events/Arguments/PlayerEvents/PlayerDeactivatedGeneratorEventArgs.cs @@ -13,11 +13,11 @@ public class PlayerDeactivatedGeneratorEventArgs : EventArgs, IPlayerEvent, IGen /// /// Initializes a new instance of the class. /// - /// The player who deactivated the generator. + /// The player who deactivated the generator. /// The generator. - public PlayerDeactivatedGeneratorEventArgs(ReferenceHub player, Scp079Generator generator) + public PlayerDeactivatedGeneratorEventArgs(ReferenceHub hub, Scp079Generator generator) { - Player = Player.Get(player); + Player = Player.Get(hub); Generator = Generator.Get(generator); } diff --git a/LabApi/Events/Arguments/PlayerEvents/PlayerDeactivatingGeneratorEventArgs.cs b/LabApi/Events/Arguments/PlayerEvents/PlayerDeactivatingGeneratorEventArgs.cs index 57bbf5b6..cd9e95fe 100644 --- a/LabApi/Events/Arguments/PlayerEvents/PlayerDeactivatingGeneratorEventArgs.cs +++ b/LabApi/Events/Arguments/PlayerEvents/PlayerDeactivatingGeneratorEventArgs.cs @@ -8,17 +8,17 @@ namespace LabApi.Events.Arguments.PlayerEvents; /// /// Represents the arguments for the event. /// -public class PlayerDeactivatingGeneratorEventArgs : EventArgs, IGeneratorEvent, ICancellableEvent +public class PlayerDeactivatingGeneratorEventArgs : EventArgs, IGeneratorEvent, ICancellableEvent, IPlayerEvent { /// /// Initializes a new instance of the class. /// - /// The player who is deactivating the generator. + /// The player who is deactivating the generator. /// The generator. - public PlayerDeactivatingGeneratorEventArgs(ReferenceHub player, Scp079Generator generator) + public PlayerDeactivatingGeneratorEventArgs(ReferenceHub hub, Scp079Generator generator) { IsAllowed = true; - Player = Player.Get(player); + Player = Player.Get(hub); Generator = Generator.Get(generator); } diff --git a/LabApi/Events/Arguments/PlayerEvents/PlayerDeathEventArgs.cs b/LabApi/Events/Arguments/PlayerEvents/PlayerDeathEventArgs.cs index d58359eb..7278b54b 100644 --- a/LabApi/Events/Arguments/PlayerEvents/PlayerDeathEventArgs.cs +++ b/LabApi/Events/Arguments/PlayerEvents/PlayerDeathEventArgs.cs @@ -15,17 +15,23 @@ public class PlayerDeathEventArgs : EventArgs, IPlayerEvent /// /// Initializes a new instance of the class. /// - /// The player who died. + /// The player who died. /// The player who caused the death. /// The damage that caused the death. /// The previous role of the player before death. /// The previous world position of the player before death. /// The previous velocity of the player before death. /// The previous world rotation of the players camera before death. - public PlayerDeathEventArgs(ReferenceHub player, ReferenceHub? attacker, DamageHandlerBase damageHandler, - RoleTypeId oldRole, Vector3 oldPosition, Vector3 oldVelocity, Quaternion oldCameraRotation) + public PlayerDeathEventArgs( + ReferenceHub hub, + ReferenceHub? attacker, + DamageHandlerBase damageHandler, + RoleTypeId oldRole, + Vector3 oldPosition, + Vector3 oldVelocity, + Quaternion oldCameraRotation) { - Player = Player.Get(player); + Player = Player.Get(hub); Attacker = Player.Get(attacker); DamageHandler = damageHandler; OldRole = oldRole; diff --git a/LabApi/Events/Arguments/PlayerEvents/PlayerDetectedByScp1344EventArgs.cs b/LabApi/Events/Arguments/PlayerEvents/PlayerDetectedByScp1344EventArgs.cs new file mode 100644 index 00000000..7fb7dd84 --- /dev/null +++ b/LabApi/Events/Arguments/PlayerEvents/PlayerDetectedByScp1344EventArgs.cs @@ -0,0 +1,28 @@ +using LabApi.Events.Arguments.Interfaces; +using LabApi.Features.Wrappers; +using System; + +namespace LabApi.Events.Arguments.PlayerEvents; + +/// +/// Represents the arguments for the event. +/// +public class PlayerDetectedByScp1344EventArgs : EventArgs, IPlayerEvent, ITargetEvent +{ + /// + /// Initializes a new instance of the class. + /// + /// The player who has SCP-1344. + /// The player who has been detected. + public PlayerDetectedByScp1344EventArgs(ReferenceHub player, ReferenceHub target) + { + Player = Player.Get(player); + Target = Player.Get(target); + } + + /// + public Player Player { get; } + + /// + public Player Target { get; set; } +} diff --git a/LabApi/Events/Arguments/PlayerEvents/PlayerDroppedAmmoEventArgs.cs b/LabApi/Events/Arguments/PlayerEvents/PlayerDroppedAmmoEventArgs.cs index 1e9b60fd..c5a47655 100644 --- a/LabApi/Events/Arguments/PlayerEvents/PlayerDroppedAmmoEventArgs.cs +++ b/LabApi/Events/Arguments/PlayerEvents/PlayerDroppedAmmoEventArgs.cs @@ -13,13 +13,13 @@ public class PlayerDroppedAmmoEventArgs : EventArgs, IPlayerEvent, IAmmoPickupEv /// /// Initializes a new instance of the class. /// - /// The player who is dropping the ammo. + /// The player who is dropping the ammo. /// The type of ammo being dropped. /// The amount of ammo being dropped. /// The ammo pickup. - public PlayerDroppedAmmoEventArgs(ReferenceHub player, ItemType type, int amount, BaseAmmoPickup pickup) + public PlayerDroppedAmmoEventArgs(ReferenceHub hub, ItemType type, int amount, BaseAmmoPickup pickup) { - Player = Player.Get(player); + Player = Player.Get(hub); Type = type; Amount = amount; AmmoPickup = AmmoPickup.Get(pickup); diff --git a/LabApi/Events/Arguments/PlayerEvents/PlayerDroppedItemEventArgs.cs b/LabApi/Events/Arguments/PlayerEvents/PlayerDroppedItemEventArgs.cs index 9dd3ff9e..5895c0bd 100644 --- a/LabApi/Events/Arguments/PlayerEvents/PlayerDroppedItemEventArgs.cs +++ b/LabApi/Events/Arguments/PlayerEvents/PlayerDroppedItemEventArgs.cs @@ -13,12 +13,12 @@ public class PlayerDroppedItemEventArgs : EventArgs, IPlayerEvent, IPickupEvent /// /// Initializes a new instance of the class. /// - /// The player who dropped the item. + /// The player who dropped the item. /// The item pickup. /// Whether the item will be thrown. - public PlayerDroppedItemEventArgs(ReferenceHub player, ItemPickupBase pickup, bool isThrowing) + public PlayerDroppedItemEventArgs(ReferenceHub hub, ItemPickupBase pickup, bool isThrowing) { - Player = Player.Get(player); + Player = Player.Get(hub); Pickup = Pickup.Get(pickup); Throw = isThrowing; } diff --git a/LabApi/Events/Arguments/PlayerEvents/PlayerDroppingAmmoEventArgs.cs b/LabApi/Events/Arguments/PlayerEvents/PlayerDroppingAmmoEventArgs.cs index 73bc7a84..dda5faba 100644 --- a/LabApi/Events/Arguments/PlayerEvents/PlayerDroppingAmmoEventArgs.cs +++ b/LabApi/Events/Arguments/PlayerEvents/PlayerDroppingAmmoEventArgs.cs @@ -12,13 +12,13 @@ public class PlayerDroppingAmmoEventArgs : EventArgs, ICancellableEvent, IPlayer /// /// Initializes a new instance of the class. /// - /// The player who is dropping the ammo. + /// The player who is dropping the ammo. /// The type of ammo being dropped. /// The amount of ammo being dropped. - public PlayerDroppingAmmoEventArgs(ReferenceHub player, ItemType type, int amount) + public PlayerDroppingAmmoEventArgs(ReferenceHub hub, ItemType type, int amount) { IsAllowed = true; - Player = Player.Get(player); + Player = Player.Get(hub); Type = type; Amount = amount; } diff --git a/LabApi/Events/Arguments/PlayerEvents/PlayerDroppingItemEventArgs.cs b/LabApi/Events/Arguments/PlayerEvents/PlayerDroppingItemEventArgs.cs index dc5f3e4d..6e0a74cd 100644 --- a/LabApi/Events/Arguments/PlayerEvents/PlayerDroppingItemEventArgs.cs +++ b/LabApi/Events/Arguments/PlayerEvents/PlayerDroppingItemEventArgs.cs @@ -8,18 +8,18 @@ namespace LabApi.Events.Arguments.PlayerEvents; /// /// Represents the arguments for the event. /// -public class PlayerDroppingItemEventArgs : EventArgs, ICancellableEvent, IItemEvent +public class PlayerDroppingItemEventArgs : EventArgs, ICancellableEvent, IItemEvent, IPlayerEvent { /// /// Initializes a new instance of the class. /// - /// The player who is dropping the item. + /// The player who is dropping the item. /// The item being dropped. /// Whether the item will be thrown. - public PlayerDroppingItemEventArgs(ReferenceHub player, ItemBase item, bool isThrowing) + public PlayerDroppingItemEventArgs(ReferenceHub hub, ItemBase item, bool isThrowing) { IsAllowed = true; - Player = Player.Get(player); + Player = Player.Get(hub); Item = Item.Get(item); Throw = isThrowing; } diff --git a/LabApi/Events/Arguments/PlayerEvents/PlayerDryFiredWeaponEventArgs.cs b/LabApi/Events/Arguments/PlayerEvents/PlayerDryFiredWeaponEventArgs.cs index 67475bde..54ec7101 100644 --- a/LabApi/Events/Arguments/PlayerEvents/PlayerDryFiredWeaponEventArgs.cs +++ b/LabApi/Events/Arguments/PlayerEvents/PlayerDryFiredWeaponEventArgs.cs @@ -13,11 +13,11 @@ public class PlayerDryFiredWeaponEventArgs : EventArgs, IPlayerEvent, IFirearmIt /// /// Initializes a new instance of the class. /// - /// The player who dry fired. + /// The player who dry fired. /// The weapon item. - public PlayerDryFiredWeaponEventArgs(ReferenceHub player, Firearm weapon) + public PlayerDryFiredWeaponEventArgs(ReferenceHub hub, Firearm weapon) { - Player = Player.Get(player); + Player = Player.Get(hub); FirearmItem = FirearmItem.Get(weapon); } diff --git a/LabApi/Events/Arguments/PlayerEvents/PlayerDryFiringWeaponEventArgs.cs b/LabApi/Events/Arguments/PlayerEvents/PlayerDryFiringWeaponEventArgs.cs index 61d62ffe..b2d3a93e 100644 --- a/LabApi/Events/Arguments/PlayerEvents/PlayerDryFiringWeaponEventArgs.cs +++ b/LabApi/Events/Arguments/PlayerEvents/PlayerDryFiringWeaponEventArgs.cs @@ -8,17 +8,17 @@ namespace LabApi.Events.Arguments.PlayerEvents; /// /// Represents the arguments for the event. /// -public class PlayerDryFiringWeaponEventArgs : EventArgs, IFirearmItemEvent, ICancellableEvent +public class PlayerDryFiringWeaponEventArgs : EventArgs, IFirearmItemEvent, ICancellableEvent, IPlayerEvent { /// /// Initializes a new instance of the class. /// - /// The player who is dry firing. + /// The player who is dry firing. /// The weapon item. - public PlayerDryFiringWeaponEventArgs(ReferenceHub player, Firearm weapon) + public PlayerDryFiringWeaponEventArgs(ReferenceHub hub, Firearm weapon) { IsAllowed = true; - Player = Player.Get(player); + Player = Player.Get(hub); FirearmItem = FirearmItem.Get(weapon); } @@ -38,5 +38,4 @@ public PlayerDryFiringWeaponEventArgs(ReferenceHub player, Firearm weapon) /// [Obsolete($"Use {nameof(FirearmItem)} instead")] public Item Weapon => FirearmItem; - } \ No newline at end of file diff --git a/LabApi/Events/Arguments/PlayerEvents/PlayerDyingEventArgs.cs b/LabApi/Events/Arguments/PlayerEvents/PlayerDyingEventArgs.cs index 70dafb23..6fb84cb2 100644 --- a/LabApi/Events/Arguments/PlayerEvents/PlayerDyingEventArgs.cs +++ b/LabApi/Events/Arguments/PlayerEvents/PlayerDyingEventArgs.cs @@ -13,13 +13,13 @@ public class PlayerDyingEventArgs : EventArgs, ICancellableEvent, IPlayerEvent /// /// Initializes a new instance of the class. /// - /// The player who is dying. + /// The player who is dying. /// The player who attacked. /// The damage handler who is causing death. - public PlayerDyingEventArgs(ReferenceHub player, ReferenceHub? attacker, DamageHandlerBase damageHandler) + public PlayerDyingEventArgs(ReferenceHub hub, ReferenceHub? attacker, DamageHandlerBase damageHandler) { IsAllowed = true; - Player = Player.Get(player); + Player = Player.Get(hub); Attacker = Player.Get(attacker); DamageHandler = damageHandler; } diff --git a/LabApi/Events/Arguments/PlayerEvents/PlayerEffectUpdatedEventArgs.cs b/LabApi/Events/Arguments/PlayerEvents/PlayerEffectUpdatedEventArgs.cs index add1ddbb..086c0bb7 100644 --- a/LabApi/Events/Arguments/PlayerEvents/PlayerEffectUpdatedEventArgs.cs +++ b/LabApi/Events/Arguments/PlayerEvents/PlayerEffectUpdatedEventArgs.cs @@ -13,13 +13,13 @@ public class PlayerEffectUpdatedEventArgs : EventArgs, IPlayerEvent /// /// Initializes a new instance of the class. /// - /// The player whose effect has been updated. + /// The player whose effect has been updated. /// The effect that is being updated. /// Intensity of the effect. /// Duration of the effect in seconds. - public PlayerEffectUpdatedEventArgs(ReferenceHub player, StatusEffectBase effect, byte intensity, float duration) + public PlayerEffectUpdatedEventArgs(ReferenceHub hub, StatusEffectBase effect, byte intensity, float duration) { - Player = Player.Get(player); + Player = Player.Get(hub); Effect = effect; Intensity = intensity; Duration = duration; diff --git a/LabApi/Events/Arguments/PlayerEvents/PlayerEffectUpdatingEventArgs.cs b/LabApi/Events/Arguments/PlayerEvents/PlayerEffectUpdatingEventArgs.cs index 54c84d53..40d30c2f 100644 --- a/LabApi/Events/Arguments/PlayerEvents/PlayerEffectUpdatingEventArgs.cs +++ b/LabApi/Events/Arguments/PlayerEvents/PlayerEffectUpdatingEventArgs.cs @@ -8,19 +8,19 @@ namespace LabApi.Events.Arguments.PlayerEvents; /// /// Represents the arguments for the event. /// -public class PlayerEffectUpdatingEventArgs : EventArgs, ICancellableEvent +public class PlayerEffectUpdatingEventArgs : EventArgs, ICancellableEvent, IPlayerEvent { /// /// Initializes a new instance of the class. /// - /// The player whose effect is being updated. + /// The player whose effect is being updated. /// The effect that is being updated. /// Intensity of the effect. /// Duration of the effect in seconds. - public PlayerEffectUpdatingEventArgs(ReferenceHub player, StatusEffectBase effect, byte intensity, float duration) + public PlayerEffectUpdatingEventArgs(ReferenceHub hub, StatusEffectBase effect, byte intensity, float duration) { IsAllowed = true; - Player = Player.Get(player); + Player = Player.Get(hub); Effect = effect; Intensity = intensity; Duration = duration; diff --git a/LabApi/Events/Arguments/PlayerEvents/PlayerEnteredHazardEventArgs.cs b/LabApi/Events/Arguments/PlayerEvents/PlayerEnteredHazardEventArgs.cs index 922a47f3..2eabbba9 100644 --- a/LabApi/Events/Arguments/PlayerEvents/PlayerEnteredHazardEventArgs.cs +++ b/LabApi/Events/Arguments/PlayerEvents/PlayerEnteredHazardEventArgs.cs @@ -13,11 +13,11 @@ public class PlayerEnteredHazardEventArgs : EventArgs, IPlayerEvent, IHazardEven /// /// Initializes a new instance of the class. /// - /// The player who entered the hazard. + /// The player who entered the hazard. /// The hazard. - public PlayerEnteredHazardEventArgs(ReferenceHub player, EnvironmentalHazard hazard) + public PlayerEnteredHazardEventArgs(ReferenceHub hub, EnvironmentalHazard hazard) { - Player = Player.Get(player); + Player = Player.Get(hub); Hazard = Hazard.Get(hazard); } diff --git a/LabApi/Events/Arguments/PlayerEvents/PlayerEnteredPocketDimensionEventArgs.cs b/LabApi/Events/Arguments/PlayerEvents/PlayerEnteredPocketDimensionEventArgs.cs index 33047082..64ca30ea 100644 --- a/LabApi/Events/Arguments/PlayerEvents/PlayerEnteredPocketDimensionEventArgs.cs +++ b/LabApi/Events/Arguments/PlayerEvents/PlayerEnteredPocketDimensionEventArgs.cs @@ -12,14 +12,14 @@ public class PlayerEnteredPocketDimensionEventArgs : EventArgs, IPlayerEvent /// /// Initializes a new instance of the class. /// - /// The player who entered the pocket dimension. - public PlayerEnteredPocketDimensionEventArgs(ReferenceHub player) + /// The player who entered the pocket dimension. + public PlayerEnteredPocketDimensionEventArgs(ReferenceHub hub) { - Player = Player.Get(player); + Player = Player.Get(hub); } /// /// Gets the player who entered the pocket dimension. /// - public Player Player { get; } + public Player Player { get; } } \ No newline at end of file diff --git a/LabApi/Events/Arguments/PlayerEvents/PlayerEnteringHazardEventArgs.cs b/LabApi/Events/Arguments/PlayerEvents/PlayerEnteringHazardEventArgs.cs index 65c547a2..8b695f81 100644 --- a/LabApi/Events/Arguments/PlayerEvents/PlayerEnteringHazardEventArgs.cs +++ b/LabApi/Events/Arguments/PlayerEvents/PlayerEnteringHazardEventArgs.cs @@ -13,11 +13,11 @@ public class PlayerEnteringHazardEventArgs : EventArgs, IPlayerEvent, IHazardEve /// /// Initializes a new instance of the class. /// - /// The player who entered the hazard. + /// The player who entered the hazard. /// The hazard. - public PlayerEnteringHazardEventArgs(ReferenceHub player, EnvironmentalHazard hazard) + public PlayerEnteringHazardEventArgs(ReferenceHub hub, EnvironmentalHazard hazard) { - Player = Player.Get(player); + Player = Player.Get(hub); Hazard = Hazard.Get(hazard); IsAllowed = true; @@ -38,4 +38,3 @@ public PlayerEnteringHazardEventArgs(ReferenceHub player, EnvironmentalHazard ha /// public bool IsAllowed { get; set; } } - diff --git a/LabApi/Events/Arguments/PlayerEvents/PlayerEnteringPocketDimensionEventArgs.cs b/LabApi/Events/Arguments/PlayerEvents/PlayerEnteringPocketDimensionEventArgs.cs index a7f4c1b0..23878f1f 100644 --- a/LabApi/Events/Arguments/PlayerEvents/PlayerEnteringPocketDimensionEventArgs.cs +++ b/LabApi/Events/Arguments/PlayerEvents/PlayerEnteringPocketDimensionEventArgs.cs @@ -12,11 +12,11 @@ public class PlayerEnteringPocketDimensionEventArgs : EventArgs, IPlayerEvent, I /// /// Initializes a new instance of the class. /// - /// The player who is entering the pocket dimension. - public PlayerEnteringPocketDimensionEventArgs(ReferenceHub player) + /// The player who is entering the pocket dimension. + public PlayerEnteringPocketDimensionEventArgs(ReferenceHub hub) { IsAllowed = true; - Player = Player.Get(player); + Player = Player.Get(hub); } /// diff --git a/LabApi/Events/Arguments/PlayerEvents/PlayerEscapedEventArgs.cs b/LabApi/Events/Arguments/PlayerEvents/PlayerEscapedEventArgs.cs index bd427268..25859366 100644 --- a/LabApi/Events/Arguments/PlayerEvents/PlayerEscapedEventArgs.cs +++ b/LabApi/Events/Arguments/PlayerEvents/PlayerEscapedEventArgs.cs @@ -2,6 +2,7 @@ using LabApi.Features.Wrappers; using PlayerRoles; using System; +using UnityEngine; using static Escape; namespace LabApi.Events.Arguments.PlayerEvents; @@ -14,14 +15,18 @@ public class PlayerEscapedEventArgs : EventArgs, IPlayerEvent /// /// Initializes a new instance of the class. /// - /// The player who escaped. + /// The player who escaped. /// The new role. /// The scenario of the escape. - public PlayerEscapedEventArgs(ReferenceHub player, RoleTypeId newRole, EscapeScenarioType escapeScenarioType) + /// The old role of the player. + /// The bounds of the escape zone that was triggered. + public PlayerEscapedEventArgs(ReferenceHub hub, RoleTypeId oldRole, RoleTypeId newRole, EscapeScenarioType escapeScenarioType, Bounds escapeZone) { - Player = Player.Get(player); + Player = Player.Get(hub); + OldRole = oldRole; NewRole = newRole; EscapeScenarioType = escapeScenarioType; + EscapeZone = escapeZone; } /// @@ -29,6 +34,11 @@ public PlayerEscapedEventArgs(ReferenceHub player, RoleTypeId newRole, EscapeSce /// public Player Player { get; } + /// + /// Gets the old role of the player. + /// + public RoleTypeId OldRole { get; } + /// /// Gets the new role. /// @@ -38,4 +48,9 @@ public PlayerEscapedEventArgs(ReferenceHub player, RoleTypeId newRole, EscapeSce /// Escape scenario of the player. /// public EscapeScenarioType EscapeScenarioType { get; } + + /// + /// The bounds of the escape zone that was triggered. + /// + public Bounds EscapeZone { get; } } \ No newline at end of file diff --git a/LabApi/Events/Arguments/PlayerEvents/PlayerEscapingEventArgs.cs b/LabApi/Events/Arguments/PlayerEvents/PlayerEscapingEventArgs.cs index 1634f83f..d604b16c 100644 --- a/LabApi/Events/Arguments/PlayerEvents/PlayerEscapingEventArgs.cs +++ b/LabApi/Events/Arguments/PlayerEvents/PlayerEscapingEventArgs.cs @@ -2,6 +2,7 @@ using LabApi.Features.Wrappers; using PlayerRoles; using System; +using UnityEngine; using static Escape; namespace LabApi.Events.Arguments.PlayerEvents; @@ -14,15 +15,19 @@ public class PlayerEscapingEventArgs : EventArgs, IPlayerEvent, ICancellableEven /// /// Initializes a new instance of the class. /// - /// The player who is escaping. + /// The player who is escaping. /// The new role that is set after escape. /// The scenario of the escape. - public PlayerEscapingEventArgs(ReferenceHub player, RoleTypeId newRole, EscapeScenarioType escapeScenario) + /// The old role of the player. + /// The bounds of the escape zone that was triggered. + public PlayerEscapingEventArgs(ReferenceHub hub, RoleTypeId oldRole, RoleTypeId newRole, EscapeScenarioType escapeScenario, Bounds escapeZone) { IsAllowed = true; - Player = Player.Get(player); + Player = Player.Get(hub); + OldRole = oldRole; NewRole = newRole; EscapeScenario = escapeScenario; + EscapeZone = escapeZone; } /// @@ -30,16 +35,26 @@ public PlayerEscapingEventArgs(ReferenceHub player, RoleTypeId newRole, EscapeSc /// public Player Player { get; } + /// + /// Gets the old role of the player. + /// + public RoleTypeId OldRole { get; } + /// /// Gets or sets the new role that is set after escape. /// public RoleTypeId NewRole { get; set; } /// - /// Gets or sets the escape scenario + /// Gets or sets the escape scenario. /// public EscapeScenarioType EscapeScenario { get; set; } + /// + /// The bounds of the escape zone that was triggered. + /// + public Bounds EscapeZone { get; } + /// public bool IsAllowed { get; set; } } \ No newline at end of file diff --git a/LabApi/Events/Arguments/PlayerEvents/PlayerFlippedCoinEventArgs.cs b/LabApi/Events/Arguments/PlayerEvents/PlayerFlippedCoinEventArgs.cs index f2defb2d..3277f32d 100644 --- a/LabApi/Events/Arguments/PlayerEvents/PlayerFlippedCoinEventArgs.cs +++ b/LabApi/Events/Arguments/PlayerEvents/PlayerFlippedCoinEventArgs.cs @@ -13,12 +13,12 @@ public class PlayerFlippedCoinEventArgs : EventArgs, IPlayerEvent, ICoinItemEven /// /// Initializes a new instance of the class. /// - /// The player who flipped the coin. + /// The player who flipped the coin. /// The coin that was flipped. /// Whenever the coin flip is tails. - public PlayerFlippedCoinEventArgs(ReferenceHub player, Coin coin, bool isTails) + public PlayerFlippedCoinEventArgs(ReferenceHub hub, Coin coin, bool isTails) { - Player = Player.Get(player); + Player = Player.Get(hub); CoinItem = CoinItem.Get(coin); IsTails = isTails; } diff --git a/LabApi/Events/Arguments/PlayerEvents/PlayerFlippingCoinEventArgs.cs b/LabApi/Events/Arguments/PlayerEvents/PlayerFlippingCoinEventArgs.cs index 84c1d6ad..16037336 100644 --- a/LabApi/Events/Arguments/PlayerEvents/PlayerFlippingCoinEventArgs.cs +++ b/LabApi/Events/Arguments/PlayerEvents/PlayerFlippingCoinEventArgs.cs @@ -8,17 +8,17 @@ namespace LabApi.Events.Arguments.PlayerEvents; /// /// Represents the arguments for the event. /// -public class PlayerFlippingCoinEventArgs : EventArgs, ICancellableEvent, ICoinItemEvent +public class PlayerFlippingCoinEventArgs : EventArgs, ICancellableEvent, ICoinItemEvent, IPlayerEvent { /// /// Initializes a new instance of the class. /// - /// The player who is flipping the coin. + /// The player who is flipping the coin. /// The coin that is being flipped. /// Whenever the coin flip is tails. - public PlayerFlippingCoinEventArgs(ReferenceHub player, Coin coin, bool isTails) + public PlayerFlippingCoinEventArgs(ReferenceHub hub, Coin coin, bool isTails) { - Player = Player.Get(player); + Player = Player.Get(hub); CoinItem = CoinItem.Get(coin); IsTails = isTails; IsAllowed = true; diff --git a/LabApi/Events/Arguments/PlayerEvents/PlayerGroupChangedEventArgs.cs b/LabApi/Events/Arguments/PlayerEvents/PlayerGroupChangedEventArgs.cs index 7619d60f..3c311bb9 100644 --- a/LabApi/Events/Arguments/PlayerEvents/PlayerGroupChangedEventArgs.cs +++ b/LabApi/Events/Arguments/PlayerEvents/PlayerGroupChangedEventArgs.cs @@ -12,11 +12,11 @@ public class PlayerGroupChangedEventArgs : EventArgs, IPlayerEvent, IGroupEvent /// /// Initializes a new instance of the class. /// - /// The player whose group changed. + /// The player whose group changed. /// The new group. - public PlayerGroupChangedEventArgs(ReferenceHub player, UserGroup group) + public PlayerGroupChangedEventArgs(ReferenceHub hub, UserGroup group) { - Player = Player.Get(player); + Player = Player.Get(hub); Group = group; } diff --git a/LabApi/Events/Arguments/PlayerEvents/PlayerGroupChangingEventArgs.cs b/LabApi/Events/Arguments/PlayerEvents/PlayerGroupChangingEventArgs.cs index 5e8ab249..707d7719 100644 --- a/LabApi/Events/Arguments/PlayerEvents/PlayerGroupChangingEventArgs.cs +++ b/LabApi/Events/Arguments/PlayerEvents/PlayerGroupChangingEventArgs.cs @@ -12,11 +12,11 @@ public class PlayerGroupChangingEventArgs : EventArgs, IPlayerEvent, IGroupEvent /// /// Initializes a new instance of the class. /// - /// The player whose group is changing. + /// The player whose group is changing. /// The new group. - public PlayerGroupChangingEventArgs(ReferenceHub player, UserGroup? group) + public PlayerGroupChangingEventArgs(ReferenceHub hub, UserGroup? group) { - Player = Player.Get(player); + Player = Player.Get(hub); Group = group; IsAllowed = true; } diff --git a/LabApi/Events/Arguments/PlayerEvents/PlayerIdledTeslaEventArgs.cs b/LabApi/Events/Arguments/PlayerEvents/PlayerIdledTeslaEventArgs.cs index 507e2f54..ba89ff61 100644 --- a/LabApi/Events/Arguments/PlayerEvents/PlayerIdledTeslaEventArgs.cs +++ b/LabApi/Events/Arguments/PlayerEvents/PlayerIdledTeslaEventArgs.cs @@ -1,6 +1,6 @@ -using System; -using LabApi.Events.Arguments.Interfaces; +using LabApi.Events.Arguments.Interfaces; using LabApi.Features.Wrappers; +using System; namespace LabApi.Events.Arguments.PlayerEvents; diff --git a/LabApi/Events/Arguments/PlayerEvents/PlayerIdlingTeslaEventArgs.cs b/LabApi/Events/Arguments/PlayerEvents/PlayerIdlingTeslaEventArgs.cs index a7085862..b7276ad1 100644 --- a/LabApi/Events/Arguments/PlayerEvents/PlayerIdlingTeslaEventArgs.cs +++ b/LabApi/Events/Arguments/PlayerEvents/PlayerIdlingTeslaEventArgs.cs @@ -1,6 +1,6 @@ -using System; -using LabApi.Events.Arguments.Interfaces; +using LabApi.Events.Arguments.Interfaces; using LabApi.Features.Wrappers; +using System; namespace LabApi.Events.Arguments.PlayerEvents; diff --git a/LabApi/Events/Arguments/PlayerEvents/PlayerInspectedKeycardEventArgs.cs b/LabApi/Events/Arguments/PlayerEvents/PlayerInspectedKeycardEventArgs.cs new file mode 100644 index 00000000..0cee3ce8 --- /dev/null +++ b/LabApi/Events/Arguments/PlayerEvents/PlayerInspectedKeycardEventArgs.cs @@ -0,0 +1,33 @@ +using LabApi.Events.Arguments.Interfaces; +using LabApi.Features.Wrappers; +using System; +using BaseKeycardItem = InventorySystem.Items.Keycards.KeycardItem; + +namespace LabApi.Events.Arguments.PlayerEvents; + +/// +/// Represents the arguments for the event. +/// +public class PlayerInspectedKeycardEventArgs : EventArgs, IPlayerEvent, IKeycardItemEvent +{ + /// + /// Initializes a new instance of the class. + /// + /// The player who inspected the . + /// The keycard item. + public PlayerInspectedKeycardEventArgs(ReferenceHub hub, BaseKeycardItem keycardItem) + { + Player = Player.Get(hub); + KeycardItem = KeycardItem.Get(keycardItem); + } + + /// + /// Gets the player who inspected the . + /// + public Player Player { get; } + + /// + /// Gets the keycard item. + /// + public KeycardItem KeycardItem { get; } +} diff --git a/LabApi/Events/Arguments/PlayerEvents/PlayerInspectingKeycardEventArgs.cs b/LabApi/Events/Arguments/PlayerEvents/PlayerInspectingKeycardEventArgs.cs new file mode 100644 index 00000000..668d4b87 --- /dev/null +++ b/LabApi/Events/Arguments/PlayerEvents/PlayerInspectingKeycardEventArgs.cs @@ -0,0 +1,37 @@ +using LabApi.Events.Arguments.Interfaces; +using LabApi.Features.Wrappers; +using System; +using BaseKeycardItem = InventorySystem.Items.Keycards.KeycardItem; + +namespace LabApi.Events.Arguments.PlayerEvents; + +/// +/// Represents the arguments for the event. +/// +public class PlayerInspectingKeycardEventArgs : EventArgs, IPlayerEvent, IKeycardItemEvent, ICancellableEvent +{ + /// + /// Initializes a new instance of the class. + /// + /// The player who wants to inspect the . + /// The keycard item. + public PlayerInspectingKeycardEventArgs(ReferenceHub hub, BaseKeycardItem keycardItem) + { + Player = Player.Get(hub); + KeycardItem = KeycardItem.Get(keycardItem); + IsAllowed = true; + } + + /// + /// Gets the player who wants to inspect . + /// + public Player Player { get; } + + /// + /// Gets the keycard item. + /// + public KeycardItem KeycardItem { get; } + + /// + public bool IsAllowed { get; set; } +} diff --git a/LabApi/Events/Arguments/PlayerEvents/PlayerInteractedDoorEventArgs.cs b/LabApi/Events/Arguments/PlayerEvents/PlayerInteractedDoorEventArgs.cs index 7a18c032..b63c2119 100644 --- a/LabApi/Events/Arguments/PlayerEvents/PlayerInteractedDoorEventArgs.cs +++ b/LabApi/Events/Arguments/PlayerEvents/PlayerInteractedDoorEventArgs.cs @@ -13,12 +13,12 @@ public class PlayerInteractedDoorEventArgs : EventArgs, IPlayerEvent, IDoorEvent /// /// Initializes a new instance of the class. /// - /// The player who is interacting with the door. + /// The player who is interacting with the door. /// The door that is being interacted with. /// Whenever player can open the door. - public PlayerInteractedDoorEventArgs(ReferenceHub player, DoorVariant door, bool canOpen) + public PlayerInteractedDoorEventArgs(ReferenceHub hub, DoorVariant door, bool canOpen) { - Player = Player.Get(player); + Player = Player.Get(hub); Door = Door.Get(door); CanOpen = canOpen; } diff --git a/LabApi/Events/Arguments/PlayerEvents/PlayerInteractedElevatorEventArgs.cs b/LabApi/Events/Arguments/PlayerEvents/PlayerInteractedElevatorEventArgs.cs index 3f672798..06795b30 100644 --- a/LabApi/Events/Arguments/PlayerEvents/PlayerInteractedElevatorEventArgs.cs +++ b/LabApi/Events/Arguments/PlayerEvents/PlayerInteractedElevatorEventArgs.cs @@ -13,12 +13,12 @@ public class PlayerInteractedElevatorEventArgs : EventArgs, IPlayerEvent, IEleva /// /// Initializes a new instance of the class. /// - /// The player who interacted with elevator panel. + /// The player who interacted with elevator panel. /// The elevator chamber. /// The elevator panel that was interaction done with. - public PlayerInteractedElevatorEventArgs(ReferenceHub player, ElevatorChamber elevator, ElevatorPanel panel) + public PlayerInteractedElevatorEventArgs(ReferenceHub hub, ElevatorChamber elevator, ElevatorPanel panel) { - Player = Player.Get(player); + Player = Player.Get(hub); Elevator = Elevator.Get(elevator); Panel = panel; } diff --git a/LabApi/Events/Arguments/PlayerEvents/PlayerInteractedGeneratorEventArgs.cs b/LabApi/Events/Arguments/PlayerEvents/PlayerInteractedGeneratorEventArgs.cs index 7b85020f..dad41929 100644 --- a/LabApi/Events/Arguments/PlayerEvents/PlayerInteractedGeneratorEventArgs.cs +++ b/LabApi/Events/Arguments/PlayerEvents/PlayerInteractedGeneratorEventArgs.cs @@ -14,12 +14,12 @@ public class PlayerInteractedGeneratorEventArgs : EventArgs, IPlayerEvent, IGene /// /// Initializes a new instance of the class. /// - /// The player who interacted with the generator. + /// The player who interacted with the generator. /// The generator object. /// The collider ID. - public PlayerInteractedGeneratorEventArgs(ReferenceHub player, Scp079Generator generator, GeneratorColliderId colliderId) + public PlayerInteractedGeneratorEventArgs(ReferenceHub hub, Scp079Generator generator, GeneratorColliderId colliderId) { - Player = Player.Get(player); + Player = Player.Get(hub); Generator = Generator.Get(generator); ColliderId = colliderId; } diff --git a/LabApi/Events/Arguments/PlayerEvents/PlayerInteractedLockerEventArgs.cs b/LabApi/Events/Arguments/PlayerEvents/PlayerInteractedLockerEventArgs.cs index 13348fea..50f941fa 100644 --- a/LabApi/Events/Arguments/PlayerEvents/PlayerInteractedLockerEventArgs.cs +++ b/LabApi/Events/Arguments/PlayerEvents/PlayerInteractedLockerEventArgs.cs @@ -14,13 +14,13 @@ public class PlayerInteractedLockerEventArgs : EventArgs, IPlayerEvent, ILockerE /// /// Initializes a new instance of the class. /// - /// The player who is interacted with the locker. + /// The player who is interacted with the locker. /// The locker that was interacted with. /// The chamber that was targeted. /// Whether the player was allowed to open it. - public PlayerInteractedLockerEventArgs(ReferenceHub player, BaseLocker locker, BaseLockerChamber chamber, bool canOpen) + public PlayerInteractedLockerEventArgs(ReferenceHub hub, BaseLocker locker, BaseLockerChamber chamber, bool canOpen) { - Player = Player.Get(player); + Player = Player.Get(hub); Locker = Locker.Get(locker); Chamber = LockerChamber.Get(chamber); CanOpen = canOpen; diff --git a/LabApi/Events/Arguments/PlayerEvents/PlayerInteractedScp330EventArgs.cs b/LabApi/Events/Arguments/PlayerEvents/PlayerInteractedScp330EventArgs.cs index a357d661..513166cf 100644 --- a/LabApi/Events/Arguments/PlayerEvents/PlayerInteractedScp330EventArgs.cs +++ b/LabApi/Events/Arguments/PlayerEvents/PlayerInteractedScp330EventArgs.cs @@ -1,8 +1,8 @@ -using LabApi.Events.Arguments.Interfaces; +using CustomPlayerEffects; +using InventorySystem.Items.Usables.Scp330; +using LabApi.Events.Arguments.Interfaces; using LabApi.Features.Wrappers; using System; -using CustomPlayerEffects; -using InventorySystem.Items.Usables.Scp330; namespace LabApi.Events.Arguments.PlayerEvents; @@ -14,14 +14,14 @@ public class PlayerInteractedScp330EventArgs : EventArgs, IPlayerEvent /// /// Initializes a new instance of the class. /// - /// The player who interacted with SCP-330. + /// The player who interacted with SCP-330. /// The amount of uses that target player did. /// Whenever pickup sound should have been. /// Whenever the effect was applied. /// Type of the candy which was given to the player. - public PlayerInteractedScp330EventArgs(ReferenceHub player, int uses, bool playSound, bool allowPunishment, CandyKindID type) + public PlayerInteractedScp330EventArgs(ReferenceHub hub, int uses, bool playSound, bool allowPunishment, CandyKindID type) { - Player = Player.Get(player); + Player = Player.Get(hub); Uses = uses; PlaySound = playSound; AllowPunishment = allowPunishment; @@ -49,7 +49,7 @@ public PlayerInteractedScp330EventArgs(ReferenceHub player, int uses, bool playS public bool AllowPunishment { get; } /// - /// Gets the type of the candy that has been given to the player. + /// Gets the type of the candy that has been given to the player. /// public CandyKindID CandyType { get; } } \ No newline at end of file diff --git a/LabApi/Events/Arguments/PlayerEvents/PlayerInteractedShootingTargetEventArgs.cs b/LabApi/Events/Arguments/PlayerEvents/PlayerInteractedShootingTargetEventArgs.cs index 7ff0e14c..03f02c3f 100644 --- a/LabApi/Events/Arguments/PlayerEvents/PlayerInteractedShootingTargetEventArgs.cs +++ b/LabApi/Events/Arguments/PlayerEvents/PlayerInteractedShootingTargetEventArgs.cs @@ -13,11 +13,11 @@ public class PlayerInteractedShootingTargetEventArgs : EventArgs, IPlayerEvent, /// /// Initializes a new instance of the class. /// - /// The player who interacted with the target. + /// The player who interacted with the target. /// The shooting target. - public PlayerInteractedShootingTargetEventArgs(ReferenceHub player, ShootingTarget target) + public PlayerInteractedShootingTargetEventArgs(ReferenceHub hub, ShootingTarget target) { - Player = Player.Get(player); + Player = Player.Get(hub); ShootingTarget = ShootingTargetToy.Get(target); } diff --git a/LabApi/Events/Arguments/PlayerEvents/PlayerInteractedToyEventArgs.cs b/LabApi/Events/Arguments/PlayerEvents/PlayerInteractedToyEventArgs.cs index 255d4a64..4212ff5c 100644 --- a/LabApi/Events/Arguments/PlayerEvents/PlayerInteractedToyEventArgs.cs +++ b/LabApi/Events/Arguments/PlayerEvents/PlayerInteractedToyEventArgs.cs @@ -13,11 +13,11 @@ public class PlayerInteractedToyEventArgs : EventArgs, IPlayerEvent, IInteractab /// /// Initializes a new instance of the class. /// - /// The player who interacted with the toy. + /// The player who interacted with the toy. /// The toy instance that was interacted with. - public PlayerInteractedToyEventArgs(ReferenceHub player, InvisibleInteractableToy toy) + public PlayerInteractedToyEventArgs(ReferenceHub hub, InvisibleInteractableToy toy) { - Player = Player.Get(player); + Player = Player.Get(hub); Interactable = InteractableToy.Get(toy); } diff --git a/LabApi/Events/Arguments/PlayerEvents/PlayerInteractedWarheadLeverEventArgs.cs b/LabApi/Events/Arguments/PlayerEvents/PlayerInteractedWarheadLeverEventArgs.cs new file mode 100644 index 00000000..2f165fd4 --- /dev/null +++ b/LabApi/Events/Arguments/PlayerEvents/PlayerInteractedWarheadLeverEventArgs.cs @@ -0,0 +1,30 @@ +using LabApi.Events.Arguments.Interfaces; +using LabApi.Features.Wrappers; +using System; + +namespace LabApi.Events.Arguments.PlayerEvents; + +/// +/// Represents the arguments for the event. +/// +public class PlayerInteractedWarheadLeverEventArgs : EventArgs, IPlayerEvent +{ + /// + /// Initializes a new instance of the class. + /// + /// The player who interacted with the lever. + /// Bool whether the warhead is enabled and can be started. + public PlayerInteractedWarheadLeverEventArgs(ReferenceHub player, bool enabled) + { + Player = Player.Get(player); + Enabled = enabled; + } + + /// + public Player Player { get; } + + /// + /// Gets whether the warhead is now enabled. + /// + public bool Enabled { get; } +} diff --git a/LabApi/Events/Arguments/PlayerEvents/PlayerInteractingDoorEventArgs.cs b/LabApi/Events/Arguments/PlayerEvents/PlayerInteractingDoorEventArgs.cs index 012e450f..b08eedf9 100644 --- a/LabApi/Events/Arguments/PlayerEvents/PlayerInteractingDoorEventArgs.cs +++ b/LabApi/Events/Arguments/PlayerEvents/PlayerInteractingDoorEventArgs.cs @@ -8,18 +8,18 @@ namespace LabApi.Events.Arguments.PlayerEvents; /// /// Represents the arguments for the event. /// -public class PlayerInteractingDoorEventArgs : EventArgs, IDoorEvent, ICancellableEvent +public class PlayerInteractingDoorEventArgs : EventArgs, IDoorEvent, ICancellableEvent, IPlayerEvent { /// /// Initializes a new instance of the class. /// - /// The player who is interacting with the door. + /// The player who is interacting with the door. /// The door that is being interacted with. /// Whenever player can open the door. - public PlayerInteractingDoorEventArgs(ReferenceHub player, DoorVariant door, bool canOpen) + public PlayerInteractingDoorEventArgs(ReferenceHub hub, DoorVariant door, bool canOpen) { IsAllowed = true; - Player = Player.Get(player); + Player = Player.Get(hub); Door = Door.Get(door); CanOpen = canOpen; } diff --git a/LabApi/Events/Arguments/PlayerEvents/PlayerInteractingElevatorEventArgs.cs b/LabApi/Events/Arguments/PlayerEvents/PlayerInteractingElevatorEventArgs.cs index 8197b0a6..db0b6ff4 100644 --- a/LabApi/Events/Arguments/PlayerEvents/PlayerInteractingElevatorEventArgs.cs +++ b/LabApi/Events/Arguments/PlayerEvents/PlayerInteractingElevatorEventArgs.cs @@ -1,7 +1,7 @@ -using LabApi.Events.Arguments.Interfaces; +using Interactables.Interobjects; +using LabApi.Events.Arguments.Interfaces; using LabApi.Features.Wrappers; using System; -using Interactables.Interobjects; namespace LabApi.Events.Arguments.PlayerEvents; @@ -13,13 +13,13 @@ public class PlayerInteractingElevatorEventArgs : EventArgs, IPlayerEvent, IElev /// /// Initializes a new instance of the class. /// - /// The player who is interacting with the elevator. + /// The player who is interacting with the elevator. /// The elevator. /// The elevator panel. - public PlayerInteractingElevatorEventArgs(ReferenceHub player, ElevatorChamber elevator, ElevatorPanel panel) + public PlayerInteractingElevatorEventArgs(ReferenceHub hub, ElevatorChamber elevator, ElevatorPanel panel) { IsAllowed = true; - Player = Player.Get(player); + Player = Player.Get(hub); Elevator = Elevator.Get(elevator); Panel = panel; } diff --git a/LabApi/Events/Arguments/PlayerEvents/PlayerInteractingGeneratorEventArgs.cs b/LabApi/Events/Arguments/PlayerEvents/PlayerInteractingGeneratorEventArgs.cs index 72d0821b..406d7911 100644 --- a/LabApi/Events/Arguments/PlayerEvents/PlayerInteractingGeneratorEventArgs.cs +++ b/LabApi/Events/Arguments/PlayerEvents/PlayerInteractingGeneratorEventArgs.cs @@ -14,13 +14,13 @@ public class PlayerInteractingGeneratorEventArgs : EventArgs, IPlayerEvent, IGen /// /// Initializes a new instance of the class. /// - /// The player who is interacting with the generator. + /// The player who is interacting with the generator. /// The generator object. /// The collider ID. - public PlayerInteractingGeneratorEventArgs(ReferenceHub player, Scp079Generator generator, GeneratorColliderId colliderId) + public PlayerInteractingGeneratorEventArgs(ReferenceHub hub, Scp079Generator generator, GeneratorColliderId colliderId) { IsAllowed = true; - Player = Player.Get(player); + Player = Player.Get(hub); Generator = Generator.Get(generator); ColliderId = colliderId; } diff --git a/LabApi/Events/Arguments/PlayerEvents/PlayerInteractingLockerEventArgs.cs b/LabApi/Events/Arguments/PlayerEvents/PlayerInteractingLockerEventArgs.cs index 3538eb32..7db994d4 100644 --- a/LabApi/Events/Arguments/PlayerEvents/PlayerInteractingLockerEventArgs.cs +++ b/LabApi/Events/Arguments/PlayerEvents/PlayerInteractingLockerEventArgs.cs @@ -14,14 +14,14 @@ public class PlayerInteractingLockerEventArgs : EventArgs, IPlayerEvent, ILocker /// /// Initializes a new instance of the class. /// - /// The player who is interacting with the locker. + /// The player who is interacting with the locker. /// The locker that is being interacted with. /// The chamber that is being targeted. /// Whether the player is allowed to open it. - public PlayerInteractingLockerEventArgs(ReferenceHub player, BaseLocker locker, BaseLockerChamber chamber, bool canOpen) + public PlayerInteractingLockerEventArgs(ReferenceHub hub, BaseLocker locker, BaseLockerChamber chamber, bool canOpen) { IsAllowed = true; - Player = Player.Get(player); + Player = Player.Get(hub); Locker = Locker.Get(locker); Chamber = LockerChamber.Get(chamber); CanOpen = canOpen; diff --git a/LabApi/Events/Arguments/PlayerEvents/PlayerInteractingScp330EventArgs.cs b/LabApi/Events/Arguments/PlayerEvents/PlayerInteractingScp330EventArgs.cs index f3f4c54f..16e8ae00 100644 --- a/LabApi/Events/Arguments/PlayerEvents/PlayerInteractingScp330EventArgs.cs +++ b/LabApi/Events/Arguments/PlayerEvents/PlayerInteractingScp330EventArgs.cs @@ -1,8 +1,8 @@ -using LabApi.Events.Arguments.Interfaces; +using CustomPlayerEffects; +using InventorySystem.Items.Usables.Scp330; +using LabApi.Events.Arguments.Interfaces; using LabApi.Features.Wrappers; using System; -using CustomPlayerEffects; -using InventorySystem.Items.Usables.Scp330; namespace LabApi.Events.Arguments.PlayerEvents; @@ -14,15 +14,15 @@ public class PlayerInteractingScp330EventArgs : EventArgs, IPlayerEvent, ICancel /// /// Initializes a new instance of the class. /// - /// The player who is interacting with SCP-330. + /// The player who is interacting with SCP-330. /// The amount of uses that target player did. /// Whenever the sound should be played of pickup up candy. /// Whenever the effect should be applied. /// Type of the candy which will be given to the player. - public PlayerInteractingScp330EventArgs(ReferenceHub player, int uses, bool playSound, bool allowPunishment, CandyKindID type) + public PlayerInteractingScp330EventArgs(ReferenceHub hub, int uses, bool playSound, bool allowPunishment, CandyKindID type) { IsAllowed = true; - Player = Player.Get(player); + Player = Player.Get(hub); Uses = uses; PlaySound = playSound; AllowPunishment = allowPunishment; @@ -50,7 +50,7 @@ public PlayerInteractingScp330EventArgs(ReferenceHub player, int uses, bool play public bool AllowPunishment { get; set; } /// - /// Gets or sets the type of the candy that is given to the player. + /// Gets or sets the type of the candy that is given to the player. /// /// Set or this to if you don't want to give candy to the player. /// diff --git a/LabApi/Events/Arguments/PlayerEvents/PlayerInteractingShootingTargetEventArgs.cs b/LabApi/Events/Arguments/PlayerEvents/PlayerInteractingShootingTargetEventArgs.cs index df6805a6..f27d42a5 100644 --- a/LabApi/Events/Arguments/PlayerEvents/PlayerInteractingShootingTargetEventArgs.cs +++ b/LabApi/Events/Arguments/PlayerEvents/PlayerInteractingShootingTargetEventArgs.cs @@ -13,12 +13,12 @@ public class PlayerInteractingShootingTargetEventArgs : EventArgs, IPlayerEvent, /// /// Initializes a new instance of the class. /// - /// The player who is interacting with the target. + /// The player who is interacting with the target. /// The shooting target. - public PlayerInteractingShootingTargetEventArgs(ReferenceHub player, ShootingTarget target) + public PlayerInteractingShootingTargetEventArgs(ReferenceHub hub, ShootingTarget target) { IsAllowed = true; - Player = Player.Get(player); + Player = Player.Get(hub); ShootingTarget = ShootingTargetToy.Get(target); } diff --git a/LabApi/Events/Arguments/PlayerEvents/PlayerInteractingWarheadLeverEventArgs.cs b/LabApi/Events/Arguments/PlayerEvents/PlayerInteractingWarheadLeverEventArgs.cs new file mode 100644 index 00000000..8947ad74 --- /dev/null +++ b/LabApi/Events/Arguments/PlayerEvents/PlayerInteractingWarheadLeverEventArgs.cs @@ -0,0 +1,35 @@ +using LabApi.Events.Arguments.Interfaces; +using LabApi.Features.Wrappers; +using System; + +namespace LabApi.Events.Arguments.PlayerEvents; + +/// +/// Represents the arguments for the event. +/// +public class PlayerInteractingWarheadLeverEventArgs : EventArgs, IPlayerEvent, ICancellableEvent +{ + /// + /// Initializes a new instance of the class. + /// + /// The player who is interacting with the lever. + /// Bool whether the warhead should be enabled and can be started. + public PlayerInteractingWarheadLeverEventArgs(ReferenceHub player, bool enabled) + { + Player = Player.Get(player); + Enabled = enabled; + + IsAllowed = true; + } + + /// + public Player Player { get; } + + /// + /// Gets or sets whether the warhead should be enabled. + /// + public bool Enabled { get; set; } + + /// + public bool IsAllowed { get; set; } +} diff --git a/LabApi/Events/Arguments/PlayerEvents/PlayerItemUsageEffectsApplyingEventArgs.cs b/LabApi/Events/Arguments/PlayerEvents/PlayerItemUsageEffectsApplyingEventArgs.cs new file mode 100644 index 00000000..32cf63c4 --- /dev/null +++ b/LabApi/Events/Arguments/PlayerEvents/PlayerItemUsageEffectsApplyingEventArgs.cs @@ -0,0 +1,42 @@ +using LabApi.Events.Arguments.Interfaces; +using LabApi.Features.Wrappers; +using System; +using BaseUsableItem = InventorySystem.Items.Usables.UsableItem; + +namespace LabApi.Events.Arguments.PlayerEvents; + +/// +/// Represents the arguments for the event. +/// +public class PlayerItemUsageEffectsApplyingEventArgs : EventArgs, IPlayerEvent, IUsableItemEvent, ICancellableEvent +{ + /// + /// Initializes a new instance of the class. + /// + /// The component of the player using the item. + /// The item that is being used. + public PlayerItemUsageEffectsApplyingEventArgs(ReferenceHub hub, BaseUsableItem item) + { + IsAllowed = true; + Player = Player.Get(hub); + UsableItem = UsableItem.Get(item); + } + + /// + /// Gets the player using the item. + /// + public Player Player { get; } + + /// + /// Gets the item that is being used. + /// + public UsableItem UsableItem { get; } + + /// + /// Get or sets whether or not to continue the using item process when the event is canceled. + /// + public bool ContinueProcess { get; set; } + + /// + public bool IsAllowed { get; set; } +} diff --git a/LabApi/Events/Arguments/PlayerEvents/PlayerJumpedEventArgs.cs b/LabApi/Events/Arguments/PlayerEvents/PlayerJumpedEventArgs.cs new file mode 100644 index 00000000..166fdcd9 --- /dev/null +++ b/LabApi/Events/Arguments/PlayerEvents/PlayerJumpedEventArgs.cs @@ -0,0 +1,30 @@ +using LabApi.Events.Arguments.Interfaces; +using LabApi.Features.Wrappers; +using System; + +namespace LabApi.Events.Arguments.PlayerEvents; + +/// +/// Represents the arguments for the event. +/// +public class PlayerJumpedEventArgs : EventArgs, IPlayerEvent +{ + /// + /// Initializes a new instance of the class. + /// + /// The player who jumped. + /// Strength of the jump. + public PlayerJumpedEventArgs(ReferenceHub hub, float jumpStrength) + { + Player = Player.Get(hub); + JumpStrength = jumpStrength; + } + + /// + public Player Player { get; } + + /// + /// Gets the strength of the jump. + /// + public float JumpStrength { get; } +} diff --git a/LabApi/Events/Arguments/PlayerEvents/PlayerKickedEventArgs.cs b/LabApi/Events/Arguments/PlayerEvents/PlayerKickedEventArgs.cs index e0b3cc9e..731659f2 100644 --- a/LabApi/Events/Arguments/PlayerEvents/PlayerKickedEventArgs.cs +++ b/LabApi/Events/Arguments/PlayerEvents/PlayerKickedEventArgs.cs @@ -12,12 +12,12 @@ public class PlayerKickedEventArgs : EventArgs, IPlayerEvent /// /// Initializes a new instance of the class. /// - /// The player who was kicked. + /// The player who was kicked. /// The player who issued the kick. /// The reason for which is player being kicked. - public PlayerKickedEventArgs(ReferenceHub player, ReferenceHub issuer, string reason) + public PlayerKickedEventArgs(ReferenceHub hub, ReferenceHub issuer, string reason) { - Player = Player.Get(player); + Player = Player.Get(hub); Issuer = Player.Get(issuer); Reason = reason; } diff --git a/LabApi/Events/Arguments/PlayerEvents/PlayerKickingEventArgs.cs b/LabApi/Events/Arguments/PlayerEvents/PlayerKickingEventArgs.cs index f117cc37..aa841320 100644 --- a/LabApi/Events/Arguments/PlayerEvents/PlayerKickingEventArgs.cs +++ b/LabApi/Events/Arguments/PlayerEvents/PlayerKickingEventArgs.cs @@ -12,13 +12,13 @@ public class PlayerKickingEventArgs : EventArgs, IPlayerEvent, ICancellableEvent /// /// Initializes a new instance of the class. /// - /// The player who is being kicked. + /// The player who is being kicked. /// The player who is issuing the kick. /// The reason for which is player being kicked. - public PlayerKickingEventArgs(ReferenceHub player, ReferenceHub issuer, string reason) + public PlayerKickingEventArgs(ReferenceHub hub, ReferenceHub issuer, string reason) { IsAllowed = true; - Player = Player.Get(player); + Player = Player.Get(hub); Issuer = Player.Get(issuer); Reason = reason; } diff --git a/LabApi/Events/Arguments/PlayerEvents/PlayerLeavingHazardEventArgs.cs b/LabApi/Events/Arguments/PlayerEvents/PlayerLeavingHazardEventArgs.cs index 01e06192..3e67b63d 100644 --- a/LabApi/Events/Arguments/PlayerEvents/PlayerLeavingHazardEventArgs.cs +++ b/LabApi/Events/Arguments/PlayerEvents/PlayerLeavingHazardEventArgs.cs @@ -13,11 +13,11 @@ public class PlayerLeavingHazardEventArgs : EventArgs, IPlayerEvent, IHazardEven /// /// Initializes a new instance of the class. /// - /// The player who is leaving. + /// The player who is leaving. /// The hazard that the player is leaving. - public PlayerLeavingHazardEventArgs(ReferenceHub player, EnvironmentalHazard hazard) + public PlayerLeavingHazardEventArgs(ReferenceHub hub, EnvironmentalHazard hazard) { - Player = Player.Get(player); + Player = Player.Get(hub); Hazard = Hazard.Get(hazard); IsAllowed = true; @@ -34,7 +34,7 @@ public PlayerLeavingHazardEventArgs(ReferenceHub player, EnvironmentalHazard haz public Hazard Hazard { get; } /// - /// Gets or sets whether the player is allowed to leave the hazard. + /// Gets or sets whether the player is allowed to leave the hazard. /// Setting this to false will result in player keeping the hazard effects and the event will be fired again until it is allowed or the player is back within the hazard's range. /// public bool IsAllowed { get; set; } diff --git a/LabApi/Events/Arguments/PlayerEvents/PlayerLeavingPocketDimensionEventArgs.cs b/LabApi/Events/Arguments/PlayerEvents/PlayerLeavingPocketDimensionEventArgs.cs index e480979c..f78985e6 100644 --- a/LabApi/Events/Arguments/PlayerEvents/PlayerLeavingPocketDimensionEventArgs.cs +++ b/LabApi/Events/Arguments/PlayerEvents/PlayerLeavingPocketDimensionEventArgs.cs @@ -12,13 +12,13 @@ public class PlayerLeavingPocketDimensionEventArgs : EventArgs, IPlayerEvent, IC /// /// Initializes a new instance of the class. /// - /// The player who is trying to leave from pocket dimension. + /// The player who is trying to leave from pocket dimension. /// The teleport the player collided with. /// Whether it is gonna be success. - public PlayerLeavingPocketDimensionEventArgs(ReferenceHub player, PocketDimensionTeleport teleport, bool isSuccessful) + public PlayerLeavingPocketDimensionEventArgs(ReferenceHub hub, PocketDimensionTeleport teleport, bool isSuccessful) { IsAllowed = true; - Player = Player.Get(player); + Player = Player.Get(hub); Teleport = PocketTeleport.Get(teleport); IsSuccessful = isSuccessful; } diff --git a/LabApi/Events/Arguments/PlayerEvents/PlayerLeftEventArgs.cs b/LabApi/Events/Arguments/PlayerEvents/PlayerLeftEventArgs.cs index fd4ace02..a7538446 100644 --- a/LabApi/Events/Arguments/PlayerEvents/PlayerLeftEventArgs.cs +++ b/LabApi/Events/Arguments/PlayerEvents/PlayerLeftEventArgs.cs @@ -12,10 +12,10 @@ public class PlayerLeftEventArgs : EventArgs, IPlayerEvent /// /// Initializes a new instance of the class. /// - /// The player who left. - public PlayerLeftEventArgs(ReferenceHub player) + /// The player who left. + public PlayerLeftEventArgs(ReferenceHub hub) { - Player = Player.Get(player); + Player = Player.Get(hub); } /// diff --git a/LabApi/Events/Arguments/PlayerEvents/PlayerLeftHazardEventArgs.cs b/LabApi/Events/Arguments/PlayerEvents/PlayerLeftHazardEventArgs.cs index 7efcc852..2f70c2ed 100644 --- a/LabApi/Events/Arguments/PlayerEvents/PlayerLeftHazardEventArgs.cs +++ b/LabApi/Events/Arguments/PlayerEvents/PlayerLeftHazardEventArgs.cs @@ -13,11 +13,11 @@ public class PlayerLeftHazardEventArgs : EventArgs, IPlayerEvent, IHazardEvent /// /// Initializes a new instance of the class. /// - /// The player who left the hazard. + /// The player who left the hazard. /// The hazard that the player left. - public PlayerLeftHazardEventArgs(ReferenceHub player, EnvironmentalHazard hazard) + public PlayerLeftHazardEventArgs(ReferenceHub hub, EnvironmentalHazard hazard) { - Player = Player.Get(player); + Player = Player.Get(hub); Hazard = Hazard.Get(hazard); } diff --git a/LabApi/Events/Arguments/PlayerEvents/PlayerLeftPocketDimensionEventArgs.cs b/LabApi/Events/Arguments/PlayerEvents/PlayerLeftPocketDimensionEventArgs.cs index 5eac423d..667d4650 100644 --- a/LabApi/Events/Arguments/PlayerEvents/PlayerLeftPocketDimensionEventArgs.cs +++ b/LabApi/Events/Arguments/PlayerEvents/PlayerLeftPocketDimensionEventArgs.cs @@ -12,12 +12,12 @@ public class PlayerLeftPocketDimensionEventArgs : EventArgs, IPlayerEvent /// /// Initializes a new instance of the class. /// - /// The player who tried to left pocket dimension. + /// The player who tried to left pocket dimension. /// The teleport the player collided with. /// Whether the escape was successful. - public PlayerLeftPocketDimensionEventArgs(ReferenceHub player, PocketDimensionTeleport teleport, bool isSuccessful) + public PlayerLeftPocketDimensionEventArgs(ReferenceHub hub, PocketDimensionTeleport teleport, bool isSuccessful) { - Player = Player.Get(player); + Player = Player.Get(hub); Teleport = PocketTeleport.Get(teleport); IsSuccessful = isSuccessful; } diff --git a/LabApi/Events/Arguments/PlayerEvents/PlayerMovementStateChangedEventArgs.cs b/LabApi/Events/Arguments/PlayerEvents/PlayerMovementStateChangedEventArgs.cs new file mode 100644 index 00000000..81a69600 --- /dev/null +++ b/LabApi/Events/Arguments/PlayerEvents/PlayerMovementStateChangedEventArgs.cs @@ -0,0 +1,38 @@ +using LabApi.Events.Arguments.Interfaces; +using LabApi.Features.Wrappers; +using PlayerRoles.FirstPersonControl; +using System; + +namespace LabApi.Events.Arguments.PlayerEvents; + +/// +/// Represents the arguments for the event. +/// +public class PlayerMovementStateChangedEventArgs : EventArgs, IPlayerEvent +{ + /// + /// Initializes a new instance of the class. + /// + /// The player whose movement state has changed. + /// Old movement state of the player. + /// New movement state of the player. + public PlayerMovementStateChangedEventArgs(ReferenceHub hub, PlayerMovementState oldState, PlayerMovementState newState) + { + Player = Player.Get(hub); + OldState = oldState; + NewState = newState; + } + + /// + public Player Player { get; } + + /// + /// Gets the old movement state. + /// + public PlayerMovementState OldState { get; } + + /// + /// Gets the new movement state. + /// + public PlayerMovementState NewState { get; } +} diff --git a/LabApi/Events/Arguments/PlayerEvents/PlayerMutedEventArgs.cs b/LabApi/Events/Arguments/PlayerEvents/PlayerMutedEventArgs.cs index 9dffcbd3..1e777544 100644 --- a/LabApi/Events/Arguments/PlayerEvents/PlayerMutedEventArgs.cs +++ b/LabApi/Events/Arguments/PlayerEvents/PlayerMutedEventArgs.cs @@ -12,12 +12,12 @@ public class PlayerMutedEventArgs : EventArgs, IPlayerEvent /// /// Initializes a new instance of the class. /// - /// The player who was muted. + /// The player who was muted. /// The player who issued the mute. /// Whenever mute was applied to intercom. - public PlayerMutedEventArgs(ReferenceHub player, ReferenceHub issuer, bool isIntercom) + public PlayerMutedEventArgs(ReferenceHub hub, ReferenceHub issuer, bool isIntercom) { - Player = Player.Get(player); + Player = Player.Get(hub); Issuer = Player.Get(issuer); IsIntercom = isIntercom; } diff --git a/LabApi/Events/Arguments/PlayerEvents/PlayerMutingEventArgs.cs b/LabApi/Events/Arguments/PlayerEvents/PlayerMutingEventArgs.cs index 77c9e5d0..af506b62 100644 --- a/LabApi/Events/Arguments/PlayerEvents/PlayerMutingEventArgs.cs +++ b/LabApi/Events/Arguments/PlayerEvents/PlayerMutingEventArgs.cs @@ -12,13 +12,13 @@ public class PlayerMutingEventArgs : EventArgs, IPlayerEvent, ICancellableEvent /// /// Initializes a new instance of the class. /// - /// The player who is being muted. + /// The player who is being muted. /// The player who is issuing the mute. /// Whenever mute is being applied to intercom. - public PlayerMutingEventArgs(ReferenceHub player, ReferenceHub issuer, bool isIntercom) + public PlayerMutingEventArgs(ReferenceHub hub, ReferenceHub issuer, bool isIntercom) { IsAllowed = true; - Player = Player.Get(player); + Player = Player.Get(hub); Issuer = Player.Get(issuer); IsIntercom = isIntercom; } diff --git a/LabApi/Events/Arguments/PlayerEvents/PlayerOpenedGeneratorEventArgs.cs b/LabApi/Events/Arguments/PlayerEvents/PlayerOpenedGeneratorEventArgs.cs index ddde7e0b..9a5982a9 100644 --- a/LabApi/Events/Arguments/PlayerEvents/PlayerOpenedGeneratorEventArgs.cs +++ b/LabApi/Events/Arguments/PlayerEvents/PlayerOpenedGeneratorEventArgs.cs @@ -13,11 +13,11 @@ public class PlayerOpenedGeneratorEventArgs : EventArgs, IPlayerEvent, IGenerato /// /// Initializes a new instance of the class. /// - /// The player who opened the generator. + /// The player who opened the generator. /// The generator that was opened. - public PlayerOpenedGeneratorEventArgs(ReferenceHub player, Scp079Generator generator) + public PlayerOpenedGeneratorEventArgs(ReferenceHub hub, Scp079Generator generator) { - Player = Player.Get(player); + Player = Player.Get(hub); Generator = Generator.Get(generator); } diff --git a/LabApi/Events/Arguments/PlayerEvents/PlayerOpeningGeneratorEventArgs.cs b/LabApi/Events/Arguments/PlayerEvents/PlayerOpeningGeneratorEventArgs.cs index b7722cef..2e036678 100644 --- a/LabApi/Events/Arguments/PlayerEvents/PlayerOpeningGeneratorEventArgs.cs +++ b/LabApi/Events/Arguments/PlayerEvents/PlayerOpeningGeneratorEventArgs.cs @@ -13,12 +13,12 @@ public class PlayerOpeningGeneratorEventArgs : EventArgs, IPlayerEvent, IGenerat /// /// Initializes a new instance of the class. /// - /// The player who is opening the generator. + /// The player who is opening the generator. /// The generator. - public PlayerOpeningGeneratorEventArgs(ReferenceHub player, Scp079Generator generator) + public PlayerOpeningGeneratorEventArgs(ReferenceHub hub, Scp079Generator generator) { IsAllowed = true; - Player = Player.Get(player); + Player = Player.Get(hub); Generator = Generator.Get(generator); } diff --git a/LabApi/Events/Arguments/PlayerEvents/PlayerPickedUpAmmoEventArgs.cs b/LabApi/Events/Arguments/PlayerEvents/PlayerPickedUpAmmoEventArgs.cs index 125aeb02..4b818777 100644 --- a/LabApi/Events/Arguments/PlayerEvents/PlayerPickedUpAmmoEventArgs.cs +++ b/LabApi/Events/Arguments/PlayerEvents/PlayerPickedUpAmmoEventArgs.cs @@ -13,13 +13,13 @@ public class PlayerPickedUpAmmoEventArgs : EventArgs, IPlayerEvent, IAmmoPickupE /// /// Initializes a new instance of the class. /// - /// The player that picked up the ammo. + /// The player that picked up the ammo. /// Type of the ammo. /// The amount that is was picked up. /// The pickup object. - public PlayerPickedUpAmmoEventArgs(ReferenceHub player, ItemType ammoType, ushort ammoAmount, BaseAmmoPickup pickup) + public PlayerPickedUpAmmoEventArgs(ReferenceHub hub, ItemType ammoType, ushort ammoAmount, BaseAmmoPickup pickup) { - Player = Player.Get(player); + Player = Player.Get(hub); AmmoType = ammoType; AmmoAmount = ammoAmount; AmmoPickup = AmmoPickup.Get(pickup); diff --git a/LabApi/Events/Arguments/PlayerEvents/PlayerPickedUpArmorEventArgs.cs b/LabApi/Events/Arguments/PlayerEvents/PlayerPickedUpArmorEventArgs.cs index ddfdd6e3..7ca160b6 100644 --- a/LabApi/Events/Arguments/PlayerEvents/PlayerPickedUpArmorEventArgs.cs +++ b/LabApi/Events/Arguments/PlayerEvents/PlayerPickedUpArmorEventArgs.cs @@ -13,11 +13,11 @@ public class PlayerPickedUpArmorEventArgs : EventArgs, IPlayerEvent, IBodyArmorI /// /// Initializes a new instance of the class. /// - /// The player who picked up armor. + /// The player who picked up armor. /// The armor that was picked up. - public PlayerPickedUpArmorEventArgs(ReferenceHub player, BodyArmor? armor) + public PlayerPickedUpArmorEventArgs(ReferenceHub hub, BodyArmor? armor) { - Player = Player.Get(player); + Player = Player.Get(hub); BodyArmorItem = BodyArmorItem.Get(armor); } diff --git a/LabApi/Events/Arguments/PlayerEvents/PlayerPickedUpItemEventArgs.cs b/LabApi/Events/Arguments/PlayerEvents/PlayerPickedUpItemEventArgs.cs index f5c7e37f..618d429e 100644 --- a/LabApi/Events/Arguments/PlayerEvents/PlayerPickedUpItemEventArgs.cs +++ b/LabApi/Events/Arguments/PlayerEvents/PlayerPickedUpItemEventArgs.cs @@ -13,11 +13,11 @@ public class PlayerPickedUpItemEventArgs : EventArgs, IPlayerEvent, IItemEvent /// /// Initializes a new instance of the class. /// - /// The player who picked up the item. + /// The player who picked up the item. /// The item that was picked up. - public PlayerPickedUpItemEventArgs(ReferenceHub player, ItemBase item) + public PlayerPickedUpItemEventArgs(ReferenceHub hub, ItemBase item) { - Player = Player.Get(player); + Player = Player.Get(hub); Item = Item.Get(item); } diff --git a/LabApi/Events/Arguments/PlayerEvents/PlayerPickedUpScp330EventArgs.cs b/LabApi/Events/Arguments/PlayerEvents/PlayerPickedUpScp330EventArgs.cs index e82caa6d..ad357475 100644 --- a/LabApi/Events/Arguments/PlayerEvents/PlayerPickedUpScp330EventArgs.cs +++ b/LabApi/Events/Arguments/PlayerEvents/PlayerPickedUpScp330EventArgs.cs @@ -1,8 +1,8 @@ using LabApi.Events.Arguments.Interfaces; using LabApi.Features.Wrappers; using System; -using BaseScp330Pickup = InventorySystem.Items.Usables.Scp330.Scp330Pickup; using BaseScp330Bag = InventorySystem.Items.Usables.Scp330.Scp330Bag; +using BaseScp330Pickup = InventorySystem.Items.Usables.Scp330.Scp330Pickup; namespace LabApi.Events.Arguments.PlayerEvents; @@ -14,12 +14,12 @@ public class PlayerPickedUpScp330EventArgs : EventArgs, IPlayerEvent, ICandyItem /// /// Initializes a new instance of the class. /// - /// The player who picked up SCP-330. + /// The player who picked up SCP-330. /// The pickup item. /// SCP-330 bag item of the player. - public PlayerPickedUpScp330EventArgs(ReferenceHub player, BaseScp330Pickup pickup, BaseScp330Bag item) + public PlayerPickedUpScp330EventArgs(ReferenceHub hub, BaseScp330Pickup pickup, BaseScp330Bag item) { - Player = Player.Get(player); + Player = Player.Get(hub); CandyPickup = Scp330Pickup.Get(pickup); CandyItem = Scp330Item.Get(item); } diff --git a/LabApi/Events/Arguments/PlayerEvents/PlayerPickingUpAmmoEventArgs.cs b/LabApi/Events/Arguments/PlayerEvents/PlayerPickingUpAmmoEventArgs.cs index 5117fa08..a4c6f4d6 100644 --- a/LabApi/Events/Arguments/PlayerEvents/PlayerPickingUpAmmoEventArgs.cs +++ b/LabApi/Events/Arguments/PlayerEvents/PlayerPickingUpAmmoEventArgs.cs @@ -13,14 +13,14 @@ public class PlayerPickingUpAmmoEventArgs : EventArgs, IPlayerEvent, IAmmoPickup /// /// Initializes a new instance of the class. /// - /// The player who is pickup the ammo pickup. + /// The player who is pickup the ammo pickup. /// Type of the ammo. /// Amount of ammo that is being picked up. /// Ammo pickup. - public PlayerPickingUpAmmoEventArgs(ReferenceHub player, ItemType ammoType, ushort ammoAmount, BaseAmmoPickup pickup) + public PlayerPickingUpAmmoEventArgs(ReferenceHub hub, ItemType ammoType, ushort ammoAmount, BaseAmmoPickup pickup) { IsAllowed = true; - Player = Player.Get(player); + Player = Player.Get(hub); AmmoType = ammoType; AmmoAmount = ammoAmount; AmmoPickup = AmmoPickup.Get(pickup); diff --git a/LabApi/Events/Arguments/PlayerEvents/PlayerPickingUpArmorEventArgs.cs b/LabApi/Events/Arguments/PlayerEvents/PlayerPickingUpArmorEventArgs.cs index b3e39e8a..d3627f14 100644 --- a/LabApi/Events/Arguments/PlayerEvents/PlayerPickingUpArmorEventArgs.cs +++ b/LabApi/Events/Arguments/PlayerEvents/PlayerPickingUpArmorEventArgs.cs @@ -13,12 +13,12 @@ public class PlayerPickingUpArmorEventArgs : EventArgs, IPlayerEvent, IBodyArmor /// /// Initializes a new instance of the class. /// - /// The player who picked up the armor. + /// The player who picked up the armor. /// The armor pickup. - public PlayerPickingUpArmorEventArgs(ReferenceHub player, BaseBodyArmorPickup pickup) + public PlayerPickingUpArmorEventArgs(ReferenceHub hub, BaseBodyArmorPickup pickup) { IsAllowed = true; - Player = Player.Get(player); + Player = Player.Get(hub); BodyArmorPickup = BodyArmorPickup.Get(pickup); } diff --git a/LabApi/Events/Arguments/PlayerEvents/PlayerPickingUpItemEventArgs.cs b/LabApi/Events/Arguments/PlayerEvents/PlayerPickingUpItemEventArgs.cs index 4b358e8b..ca21e90d 100644 --- a/LabApi/Events/Arguments/PlayerEvents/PlayerPickingUpItemEventArgs.cs +++ b/LabApi/Events/Arguments/PlayerEvents/PlayerPickingUpItemEventArgs.cs @@ -13,12 +13,12 @@ public class PlayerPickingUpItemEventArgs : EventArgs, IPlayerEvent, IPickupEven /// /// Initializes a new instance of the class. /// - /// The player who picked up the item. + /// The player who picked up the item. /// The item pickup. - public PlayerPickingUpItemEventArgs(ReferenceHub player, ItemPickupBase pickup) + public PlayerPickingUpItemEventArgs(ReferenceHub hub, ItemPickupBase pickup) { IsAllowed = true; - Player = Player.Get(player); + Player = Player.Get(hub); Pickup = Pickup.Get(pickup); } diff --git a/LabApi/Events/Arguments/PlayerEvents/PlayerPickingUpScp330EventArgs.cs b/LabApi/Events/Arguments/PlayerEvents/PlayerPickingUpScp330EventArgs.cs index 871c1048..002743de 100644 --- a/LabApi/Events/Arguments/PlayerEvents/PlayerPickingUpScp330EventArgs.cs +++ b/LabApi/Events/Arguments/PlayerEvents/PlayerPickingUpScp330EventArgs.cs @@ -13,12 +13,12 @@ public class PlayerPickingUpScp330EventArgs : EventArgs, IPlayerEvent, ICandyPic /// /// Initializes a new instance of the class. /// - /// The player who is picking up SCP-330. + /// The player who is picking up SCP-330. /// The SCP-330 pickup. - public PlayerPickingUpScp330EventArgs(ReferenceHub player, BaseScp330Pickup pickup) + public PlayerPickingUpScp330EventArgs(ReferenceHub hub, BaseScp330Pickup pickup) { IsAllowed = true; - Player = Player.Get(player); + Player = Player.Get(hub); CandyPickup = Scp330Pickup.Get(pickup); } diff --git a/LabApi/Events/Arguments/PlayerEvents/PlayerPlacedBloodEventArgs.cs b/LabApi/Events/Arguments/PlayerEvents/PlayerPlacedBloodEventArgs.cs index e4385b58..4d76ffa7 100644 --- a/LabApi/Events/Arguments/PlayerEvents/PlayerPlacedBloodEventArgs.cs +++ b/LabApi/Events/Arguments/PlayerEvents/PlayerPlacedBloodEventArgs.cs @@ -13,13 +13,13 @@ public class PlayerPlacedBloodEventArgs : EventArgs, IPlayerEvent /// /// Initializes a new instance of the class. /// - /// The player whose blood it is. + /// The player whose blood it is. /// The player that attacked. /// Position at which blood has been spawned. /// Position where the blood decal raycast will start for it to be properly attached to surface. - public PlayerPlacedBloodEventArgs(ReferenceHub player, ReferenceHub attacker, Vector3 hitPosition, Vector3 startRaycast) + public PlayerPlacedBloodEventArgs(ReferenceHub hub, ReferenceHub attacker, Vector3 hitPosition, Vector3 startRaycast) { - Player = Player.Get(player); + Player = Player.Get(hub); Attacker = Player.Get(attacker); HitPosition = hitPosition; RaycastStart = startRaycast; diff --git a/LabApi/Events/Arguments/PlayerEvents/PlayerPlacedBulletHole.cs b/LabApi/Events/Arguments/PlayerEvents/PlayerPlacedBulletHoleEventArgs.cs similarity index 81% rename from LabApi/Events/Arguments/PlayerEvents/PlayerPlacedBulletHole.cs rename to LabApi/Events/Arguments/PlayerEvents/PlayerPlacedBulletHoleEventArgs.cs index 0c9bab18..05f4790a 100644 --- a/LabApi/Events/Arguments/PlayerEvents/PlayerPlacedBulletHole.cs +++ b/LabApi/Events/Arguments/PlayerEvents/PlayerPlacedBulletHoleEventArgs.cs @@ -5,21 +5,23 @@ namespace LabApi.Events.Arguments.PlayerEvents; +using Interfaces; + /// /// Represents the arguments for the event. /// -public class PlayerPlacedBulletHoleEventArgs : EventArgs +public class PlayerPlacedBulletHoleEventArgs : EventArgs, IPlayerEvent { /// /// Initializes a new instance of the class. /// - /// The player who caused this bullet hole. + /// The player who caused this bullet hole. /// Decal type which has spawned. /// Position at which bullet hole has spawned. /// Position where the bullet hole raycast has started for it to be properly attached to surface. - public PlayerPlacedBulletHoleEventArgs(ReferenceHub player, DecalPoolType type, Vector3 hitPosition, Vector3 startRaycast) + public PlayerPlacedBulletHoleEventArgs(ReferenceHub hub, DecalPoolType type, Vector3 hitPosition, Vector3 startRaycast) { - Player = Player.Get(player); + Player = Player.Get(hub); DecalType = type; HitPosition = hitPosition; RaycastStart = startRaycast; diff --git a/LabApi/Events/Arguments/PlayerEvents/PlayerPlacingBloodEventArgs.cs b/LabApi/Events/Arguments/PlayerEvents/PlayerPlacingBloodEventArgs.cs index cf28fff4..a34c4451 100644 --- a/LabApi/Events/Arguments/PlayerEvents/PlayerPlacingBloodEventArgs.cs +++ b/LabApi/Events/Arguments/PlayerEvents/PlayerPlacingBloodEventArgs.cs @@ -13,14 +13,14 @@ public class PlayerPlacingBloodEventArgs : EventArgs, IPlayerEvent, ICancellable /// /// Initializes a new instance of the class. /// - /// The player whose blood it is. + /// The player whose blood it is. /// The player that attacked. /// Position at which is blood being placed. /// Position where the blood decal raycast will start for it to be properly attached to surface. - public PlayerPlacingBloodEventArgs(ReferenceHub player, ReferenceHub attacker, Vector3 hitPosition, Vector3 startRaycast) + public PlayerPlacingBloodEventArgs(ReferenceHub hub, ReferenceHub attacker, Vector3 hitPosition, Vector3 startRaycast) { IsAllowed = true; - Player = Player.Get(player); + Player = Player.Get(hub); Attacker = Player.Get(attacker); HitPosition = hitPosition; RaycastStart = startRaycast; diff --git a/LabApi/Events/Arguments/PlayerEvents/PlayerPlacingBulletHoleEventArgs.cs b/LabApi/Events/Arguments/PlayerEvents/PlayerPlacingBulletHoleEventArgs.cs index ca82271a..a9929378 100644 --- a/LabApi/Events/Arguments/PlayerEvents/PlayerPlacingBulletHoleEventArgs.cs +++ b/LabApi/Events/Arguments/PlayerEvents/PlayerPlacingBulletHoleEventArgs.cs @@ -14,14 +14,14 @@ public class PlayerPlacingBulletHoleEventArgs : EventArgs, IPlayerEvent, ICancel /// /// Initializes a new instance of the class. /// - /// The player who caused it. + /// The player who caused it. /// Decal type to be spawned. /// Position at which is bullet hole being placed. /// Position where the bullet hole raycast will start for it to be properly attached to surface. - public PlayerPlacingBulletHoleEventArgs(ReferenceHub player, DecalPoolType type, Vector3 hitPosition, Vector3 startRaycast) + public PlayerPlacingBulletHoleEventArgs(ReferenceHub hub, DecalPoolType type, Vector3 hitPosition, Vector3 startRaycast) { IsAllowed = true; - Player = Player.Get(player); + Player = Player.Get(hub); DecalType = type; HitPosition = hitPosition; RaycastStart = startRaycast; diff --git a/LabApi/Events/Arguments/PlayerEvents/PlayerPreAuthenticatingEventArgs.cs b/LabApi/Events/Arguments/PlayerEvents/PlayerPreAuthenticatingEventArgs.cs index 7eace2d9..bda0c398 100644 --- a/LabApi/Events/Arguments/PlayerEvents/PlayerPreAuthenticatingEventArgs.cs +++ b/LabApi/Events/Arguments/PlayerEvents/PlayerPreAuthenticatingEventArgs.cs @@ -37,7 +37,7 @@ public PlayerPreAuthenticatingEventArgs(bool canJoin, string userId, string ipAd } /// - /// Gets or sets whether the player should be able to join server. ( this value can be false if server is full ) + /// Gets or sets whether the player should be able to join server (this value can be false if server is full). /// public bool CanJoin { get; set; } @@ -92,7 +92,7 @@ public PlayerPreAuthenticatingEventArgs(bool canJoin, string userId, string ipAd /// /// Gets or sets the custom rejection writer. /// - //TODO: Write what exactly this does and how does it work + // TODO: Write what exactly this does and how does it work public NetDataWriter? CustomReject { get; set; } /// diff --git a/LabApi/Events/Arguments/PlayerEvents/PlayerProcessedJailbirdMessageEventArgs.cs b/LabApi/Events/Arguments/PlayerEvents/PlayerProcessedJailbirdMessageEventArgs.cs new file mode 100644 index 00000000..5cd7c4b4 --- /dev/null +++ b/LabApi/Events/Arguments/PlayerEvents/PlayerProcessedJailbirdMessageEventArgs.cs @@ -0,0 +1,42 @@ +using LabApi.Events.Arguments.Interfaces; +using LabApi.Events.Arguments.Interfaces.Items; +using LabApi.Features.Wrappers; +using System; +using BaseJailbirdItem = InventorySystem.Items.Jailbird.JailbirdItem; +using JailbirdMessageType = InventorySystem.Items.Jailbird.JailbirdMessageType; + +namespace LabApi.Events.Arguments.PlayerEvents; + +/// +/// Represents the arguments for the event. +/// +public class PlayerProcessedJailbirdMessageEventArgs : EventArgs, IPlayerEvent, IJailbirdEvent +{ + /// + /// Initializes a new instance of the class. + /// + /// The component of the player that owns the jailbird. + /// Jailbird the message is for. + /// The message sent by the player for the jailbird. + public PlayerProcessedJailbirdMessageEventArgs(ReferenceHub hub, BaseJailbirdItem jailbird, JailbirdMessageType msg) + { + Player = Player.Get(hub); + JailbirdItem = JailbirdItem.Get(jailbird); + Message = msg; + } + + /// + /// The owner of the jailbird. + /// + public Player Player { get; } + + /// + /// The jailbird item. + /// + public JailbirdItem JailbirdItem { get; } + + /// + /// The processed. + /// + public JailbirdMessageType Message { get; } +} diff --git a/LabApi/Events/Arguments/PlayerEvents/PlayerProcessingJailbirdMessageEventArgs.cs b/LabApi/Events/Arguments/PlayerEvents/PlayerProcessingJailbirdMessageEventArgs.cs new file mode 100644 index 00000000..4e05e939 --- /dev/null +++ b/LabApi/Events/Arguments/PlayerEvents/PlayerProcessingJailbirdMessageEventArgs.cs @@ -0,0 +1,60 @@ +using LabApi.Events.Arguments.Interfaces; +using LabApi.Events.Arguments.Interfaces.Items; +using LabApi.Features.Wrappers; +using System; +using BaseJailbirdItem = InventorySystem.Items.Jailbird.JailbirdItem; +using JailbirdMessageType = InventorySystem.Items.Jailbird.JailbirdMessageType; + +namespace LabApi.Events.Arguments.PlayerEvents; + +/// +/// Represents the arguments for the event. +/// +public class PlayerProcessingJailbirdMessageEventArgs : EventArgs, IPlayerEvent, IJailbirdEvent, ICancellableEvent +{ + /// + /// Initializes a new instance of the class. + /// + /// The component of the player that owns the jailbird. + /// Jailbird the message is for. + /// The message sent by the player for the jailbird. + /// Whether an attack is allowed to start. + /// Whether an inspect is allowed to start. + public PlayerProcessingJailbirdMessageEventArgs(ReferenceHub hub, BaseJailbirdItem jailbird, JailbirdMessageType msg, bool allowAttack, bool allowInspect) + { + Player = Player.Get(hub); + JailbirdItem = JailbirdItem.Get(jailbird); + Message = msg; + AllowAttack = allowAttack; + AllowInspect = allowInspect; + IsAllowed = true; + } + + /// + /// The owner of the jailbird. + /// + public Player Player { get; } + + /// + /// The jailbird item. + /// + public JailbirdItem JailbirdItem { get; } + + /// + /// Gets or sets the sent by the player. + /// + public JailbirdMessageType Message { get; set; } + + /// + /// Gets or sets whether starting an attack is allowed. + /// + public bool AllowAttack { get; set; } + + /// + /// Gets or sets whether starting an inspect is allowed. + /// + public bool AllowInspect { get; set; } + + /// + public bool IsAllowed { get; set; } +} diff --git a/LabApi/Events/Arguments/PlayerEvents/PlayerRaPlayerListAddedPlayerEventArgs.cs b/LabApi/Events/Arguments/PlayerEvents/PlayerRaPlayerListAddedPlayerEventArgs.cs new file mode 100644 index 00000000..ecc2bda7 --- /dev/null +++ b/LabApi/Events/Arguments/PlayerEvents/PlayerRaPlayerListAddedPlayerEventArgs.cs @@ -0,0 +1,43 @@ +using LabApi.Events.Arguments.Interfaces; +using LabApi.Features.Wrappers; +using System; +using System.Text; + +namespace LabApi.Events.Arguments.PlayerEvents; + +/// +/// Represents the arguments for the event. +/// +public class PlayerRaPlayerListAddedPlayerEventArgs : EventArgs, IPlayerEvent, ITargetEvent +{ + /// + /// Initializes a new instance of the class. + /// + /// The instance of the player that made the request for the RA player list. + /// The component of the player that is being added to the RA player list. + /// The used to build the RA player list item. + public PlayerRaPlayerListAddedPlayerEventArgs(CommandSender requesterHub, ReferenceHub targetHub, StringBuilder builder) + { + Player = Player.Get(requesterHub)!; + Target = Player.Get(targetHub); + TargetBuilder = builder; + } + + /// + /// The player that requested the RA player list. + /// + public Player Player { get; } + + /// + /// The player that was added to the RA player list. + /// + public Player Target { get; } + + /// + /// The used to construct the RA player list item for the . + /// + /// + /// String builder is not empty in this event and contains the RA list item for the . + /// + public StringBuilder TargetBuilder { get; } +} diff --git a/LabApi/Events/Arguments/PlayerEvents/PlayerRaPlayerListAddingPlayerEventArgs.cs b/LabApi/Events/Arguments/PlayerEvents/PlayerRaPlayerListAddingPlayerEventArgs.cs new file mode 100644 index 00000000..abe6a3a6 --- /dev/null +++ b/LabApi/Events/Arguments/PlayerEvents/PlayerRaPlayerListAddingPlayerEventArgs.cs @@ -0,0 +1,85 @@ +using LabApi.Events.Arguments.Interfaces; +using LabApi.Features.Wrappers; +using System; +using System.Text; + +namespace LabApi.Events.Arguments.PlayerEvents; + +/// +/// Represents the arguments for the event. +/// +public class PlayerRaPlayerListAddingPlayerEventArgs : EventArgs, IPlayerEvent, ITargetEvent, ICancellableEvent +{ + /// + /// Initializes a new instance of the class. + /// + /// The instance of the player that made the request for the RA player list. + /// The component of the player that is being added to the RA player list. + /// The used to build the RA player list item. + /// The prefix string for the RA list item. + /// Whether to include the overwatch icon in the list item. + /// Whether to include the is muted icon and link in the list item. + /// The body string for the Ra list item. + public PlayerRaPlayerListAddingPlayerEventArgs( + CommandSender commandSender, + ReferenceHub targetHub, + StringBuilder builder, + string prefix, + bool inOverwatch, + bool isMuted, + string body) + { + Player = Player.Get(commandSender)!; + Target = Player.Get(targetHub); + TargetBuilder = builder; + Prefix = prefix; + InOverwatch = inOverwatch; + IsMuted = isMuted; + Body = body; + IsAllowed = true; + } + + /// + /// The player that requested the RA player list. + /// + public Player Player { get; } + + /// + /// The player being added to the RA player list. + /// + public Player Target { get; } + + /// + /// The used to construct the RA player list item for the . + /// + /// + /// String builder is empty in this event. + /// + public StringBuilder TargetBuilder { get; } + + /// + /// Gets or sets the RA player list item prefix. + /// Can contain a RA badge and/or link for whether the is one of either a Dummy, has RemoteAdminGlobalAccess, is NorthwoodStaff, or has RemoteAdmin. + /// Otherwise this is . + /// + public string Prefix { get; set; } + + /// + /// Gets or sets whether the appears to be in overwatch on the RA player list. + /// + public bool InOverwatch { get; set; } + + /// + /// Gets or sets whether the appears to be muted on the RA player list. + /// + public bool IsMuted { get; set; } + + /// + /// Gets or sets the RA player list item body. + /// Contains the color tags, identifier as the and of the . + /// + public string Body { get; set; } + + /// + public bool IsAllowed { get; set; } +} diff --git a/LabApi/Events/Arguments/PlayerEvents/PlayerReceivedAchievementEventArgs.cs b/LabApi/Events/Arguments/PlayerEvents/PlayerReceivedAchievementEventArgs.cs new file mode 100644 index 00000000..0f9fcdd2 --- /dev/null +++ b/LabApi/Events/Arguments/PlayerEvents/PlayerReceivedAchievementEventArgs.cs @@ -0,0 +1,34 @@ +using Achievements; +using LabApi.Events.Arguments.Interfaces; +using LabApi.Features.Wrappers; +using Mirror; +using System; + +namespace LabApi.Events.Arguments.PlayerEvents; + +/// +/// Represents the argument for the event. +/// +public class PlayerReceivedAchievementEventArgs : EventArgs, IPlayerEvent +{ + /// + /// Initializes a new instance of the class. + /// + /// The component of the player. + /// The being granted. + public PlayerReceivedAchievementEventArgs(NetworkIdentity identity, AchievementName name) + { + Player = Player.Get(identity); + Achievement = name; + } + + /// + /// The player that getting the achievement. + /// + public Player? Player { get; } + + /// + /// The of the achievement. + /// + public AchievementName Achievement { get; } +} diff --git a/LabApi/Events/Arguments/PlayerEvents/PlayerReceivedLoadoutEventArgs.cs b/LabApi/Events/Arguments/PlayerEvents/PlayerReceivedLoadoutEventArgs.cs index fd2d86c7..44fe9d79 100644 --- a/LabApi/Events/Arguments/PlayerEvents/PlayerReceivedLoadoutEventArgs.cs +++ b/LabApi/Events/Arguments/PlayerEvents/PlayerReceivedLoadoutEventArgs.cs @@ -13,13 +13,13 @@ public class PlayerReceivedLoadoutEventArgs : EventArgs, IPlayerEvent /// /// Initializes a new instance of the class. /// - /// The player instance. + /// The player instance. /// The items which player received. /// The ammo which player received. /// If players inventory did reset. - public PlayerReceivedLoadoutEventArgs(ReferenceHub player, List items, Dictionary ammo, bool inventoryReset) + public PlayerReceivedLoadoutEventArgs(ReferenceHub hub, List items, Dictionary ammo, bool inventoryReset) { - Player = Player.Get(player); + Player = Player.Get(hub); Items = items; Ammo = ammo; InventoryReset = inventoryReset; diff --git a/LabApi/Events/Arguments/PlayerEvents/PlayerReceivingLoadoutEventArgs.cs b/LabApi/Events/Arguments/PlayerEvents/PlayerReceivingLoadoutEventArgs.cs index 9e71d4bb..7ff4b159 100644 --- a/LabApi/Events/Arguments/PlayerEvents/PlayerReceivingLoadoutEventArgs.cs +++ b/LabApi/Events/Arguments/PlayerEvents/PlayerReceivingLoadoutEventArgs.cs @@ -13,14 +13,14 @@ public class PlayerReceivingLoadoutEventArgs : EventArgs, IPlayerEvent, ICancell /// /// Initializes a new instance of the class. /// - /// The player instance. + /// The player instance. /// The items which player received. /// The ammo which player received. /// If players inventory will be cleared. - public PlayerReceivingLoadoutEventArgs(ReferenceHub player, List items, Dictionary ammo, bool inventoryReset) + public PlayerReceivingLoadoutEventArgs(ReferenceHub hub, List items, Dictionary ammo, bool inventoryReset) { IsAllowed = true; - Player = Player.Get(player); + Player = Player.Get(hub); Items = items; Ammo = ammo; InventoryReset = inventoryReset; @@ -50,7 +50,7 @@ public PlayerReceivingLoadoutEventArgs(ReferenceHub player, List items public bool IsAllowed { get; set; } /// - /// Adds item of specifc type to this loadout. + /// Adds item of specific type to this loadout. /// /// The type of item. public void AddItem(ItemType type) => Items.Add(type); @@ -63,9 +63,13 @@ public PlayerReceivingLoadoutEventArgs(ReferenceHub player, List items public void AddAmmo(ItemType ammoType, ushort ammoAmount) { if (Ammo.ContainsKey(ammoType)) + { Ammo[ammoType] += ammoAmount; + } else + { Ammo.Add(ammoType, ammoAmount); + } } /// @@ -76,9 +80,13 @@ public void AddAmmo(ItemType ammoType, ushort ammoAmount) public void SetAmmo(ItemType ammoType, ushort ammoAmount) { if (Ammo.ContainsKey(ammoType)) + { Ammo[ammoType] = ammoAmount; + } else + { Ammo.Add(ammoType, ammoAmount); + } } /// diff --git a/LabApi/Events/Arguments/PlayerEvents/PlayerReceivingVoiceMessageEventArgs.cs b/LabApi/Events/Arguments/PlayerEvents/PlayerReceivingVoiceMessageEventArgs.cs index 900b07d7..8b60ebc5 100644 --- a/LabApi/Events/Arguments/PlayerEvents/PlayerReceivingVoiceMessageEventArgs.cs +++ b/LabApi/Events/Arguments/PlayerEvents/PlayerReceivingVoiceMessageEventArgs.cs @@ -10,6 +10,8 @@ namespace LabApi.Events.Arguments.PlayerEvents; /// public class PlayerReceivingVoiceMessageEventArgs : EventArgs, ICancellableEvent, IPlayerEvent, IVoiceMessageEvent { + private VoiceMessage _message; + /// /// Initializes a new instance of the class. /// @@ -45,6 +47,4 @@ public PlayerReceivingVoiceMessageEventArgs(ReferenceHub listener, ref VoiceMess /// this will be ignored. /// public bool IsAllowed { get; set; } - - private VoiceMessage _message; } \ No newline at end of file diff --git a/LabApi/Events/Arguments/PlayerEvents/PlayerReloadedWeaponEventArgs.cs b/LabApi/Events/Arguments/PlayerEvents/PlayerReloadedWeaponEventArgs.cs index 8e050093..3cbfe389 100644 --- a/LabApi/Events/Arguments/PlayerEvents/PlayerReloadedWeaponEventArgs.cs +++ b/LabApi/Events/Arguments/PlayerEvents/PlayerReloadedWeaponEventArgs.cs @@ -13,11 +13,11 @@ public class PlayerReloadedWeaponEventArgs : EventArgs, IPlayerEvent, IFirearmIt /// /// Initializes a new instance of the class. /// - /// The player who reloaded the weapon. + /// The player who reloaded the weapon. /// The weapon that was reloaded. - public PlayerReloadedWeaponEventArgs(ReferenceHub player, Firearm weapon) + public PlayerReloadedWeaponEventArgs(ReferenceHub hub, Firearm weapon) { - Player = Player.Get(player); + Player = Player.Get(hub); FirearmItem = FirearmItem.Get(weapon); } diff --git a/LabApi/Events/Arguments/PlayerEvents/PlayerReloadingWeaponEventArgs.cs b/LabApi/Events/Arguments/PlayerEvents/PlayerReloadingWeaponEventArgs.cs index f98f9781..94ae6744 100644 --- a/LabApi/Events/Arguments/PlayerEvents/PlayerReloadingWeaponEventArgs.cs +++ b/LabApi/Events/Arguments/PlayerEvents/PlayerReloadingWeaponEventArgs.cs @@ -8,17 +8,17 @@ namespace LabApi.Events.Arguments.PlayerEvents; /// /// Represents the arguments for the event. /// -public class PlayerReloadingWeaponEventArgs : EventArgs, IFirearmItemEvent, ICancellableEvent +public class PlayerReloadingWeaponEventArgs : EventArgs, IFirearmItemEvent, ICancellableEvent, IPlayerEvent { /// /// Initializes a new instance of the class. /// - /// The player who is reloading the weapon. + /// The player who is reloading the weapon. /// The weapon that is being reloaded. - public PlayerReloadingWeaponEventArgs(ReferenceHub player, Firearm weapon) + public PlayerReloadingWeaponEventArgs(ReferenceHub hub, Firearm weapon) { IsAllowed = true; - Player = Player.Get(player); + Player = Player.Get(hub); FirearmItem = FirearmItem.Get(weapon); } diff --git a/LabApi/Events/Arguments/PlayerEvents/PlayerReportedCheaterEventArgs.cs b/LabApi/Events/Arguments/PlayerEvents/PlayerReportedCheaterEventArgs.cs index bab934f8..1fe80768 100644 --- a/LabApi/Events/Arguments/PlayerEvents/PlayerReportedCheaterEventArgs.cs +++ b/LabApi/Events/Arguments/PlayerEvents/PlayerReportedCheaterEventArgs.cs @@ -12,12 +12,12 @@ public class PlayerReportedCheaterEventArgs : EventArgs, IPlayerEvent, ITargetEv /// /// Initializes a new instance of the class. /// - /// The player who sent the report. + /// The player who sent the report. /// The reported player. /// The reason why is the player being reported. - public PlayerReportedCheaterEventArgs(ReferenceHub player, ReferenceHub target, string reason) + public PlayerReportedCheaterEventArgs(ReferenceHub hub, ReferenceHub target, string reason) { - Player = Player.Get(player); + Player = Player.Get(hub); Target = Player.Get(target); Reason = reason; } diff --git a/LabApi/Events/Arguments/PlayerEvents/PlayerReportedPlayerEventArgs.cs b/LabApi/Events/Arguments/PlayerEvents/PlayerReportedPlayerEventArgs.cs index c2fa1535..bdf4c742 100644 --- a/LabApi/Events/Arguments/PlayerEvents/PlayerReportedPlayerEventArgs.cs +++ b/LabApi/Events/Arguments/PlayerEvents/PlayerReportedPlayerEventArgs.cs @@ -12,12 +12,12 @@ public class PlayerReportedPlayerEventArgs : EventArgs, IPlayerEvent, ITargetEve /// /// Initializes a new instance of the class. /// - /// The player who sent reported. + /// The player who sent reported. /// The player who was reported. /// The reason why was the player reported. - public PlayerReportedPlayerEventArgs(ReferenceHub player, ReferenceHub target, string reason) + public PlayerReportedPlayerEventArgs(ReferenceHub hub, ReferenceHub target, string reason) { - Player = Player.Get(player); + Player = Player.Get(hub); Target = Player.Get(target); Reason = reason; } diff --git a/LabApi/Events/Arguments/PlayerEvents/PlayerReportingCheaterEventArgs.cs b/LabApi/Events/Arguments/PlayerEvents/PlayerReportingCheaterEventArgs.cs index a0415daa..8f0b4ac7 100644 --- a/LabApi/Events/Arguments/PlayerEvents/PlayerReportingCheaterEventArgs.cs +++ b/LabApi/Events/Arguments/PlayerEvents/PlayerReportingCheaterEventArgs.cs @@ -12,13 +12,13 @@ public class PlayerReportingCheaterEventArgs : EventArgs, IPlayerEvent, ITargetE /// /// Initializes a new instance of the class. /// - /// The player who is reporting. + /// The player who is reporting. /// The reported player. /// The reason why is the player being reported. - public PlayerReportingCheaterEventArgs(ReferenceHub player, ReferenceHub target, string reason) + public PlayerReportingCheaterEventArgs(ReferenceHub hub, ReferenceHub target, string reason) { IsAllowed = true; - Player = Player.Get(player); + Player = Player.Get(hub); Target = Player.Get(target); Reason = reason; } diff --git a/LabApi/Events/Arguments/PlayerEvents/PlayerReportingPlayerEventArgs.cs b/LabApi/Events/Arguments/PlayerEvents/PlayerReportingPlayerEventArgs.cs index 11771f3e..aa5d5732 100644 --- a/LabApi/Events/Arguments/PlayerEvents/PlayerReportingPlayerEventArgs.cs +++ b/LabApi/Events/Arguments/PlayerEvents/PlayerReportingPlayerEventArgs.cs @@ -12,13 +12,13 @@ public class PlayerReportingPlayerEventArgs : EventArgs, IPlayerEvent, ITargetEv /// /// Initializes a new instance of the class. /// - /// The player who is reporting. + /// The player who is reporting. /// The player who is being reported. /// The reason why was player reported. - public PlayerReportingPlayerEventArgs(ReferenceHub player, ReferenceHub target, string reason) + public PlayerReportingPlayerEventArgs(ReferenceHub hub, ReferenceHub target, string reason) { IsAllowed = true; - Player = Player.Get(player); + Player = Player.Get(hub); Target = Player.Get(target); Reason = reason; } diff --git a/LabApi/Events/Arguments/PlayerEvents/PlayerRequestedCustomRaInfoEventArgs.cs b/LabApi/Events/Arguments/PlayerEvents/PlayerRequestedCustomRaInfoEventArgs.cs new file mode 100644 index 00000000..c49cdd72 --- /dev/null +++ b/LabApi/Events/Arguments/PlayerEvents/PlayerRequestedCustomRaInfoEventArgs.cs @@ -0,0 +1,118 @@ +using LabApi.Events.Arguments.Interfaces; +using LabApi.Features.Wrappers; +using System; +using System.Diagnostics.CodeAnalysis; +using System.Linq; +using System.Text; + +namespace LabApi.Events.Arguments.PlayerEvents; + +/// +/// Represents the arguments for the event. +/// +public class PlayerRequestedCustomRaInfoEventArgs : EventArgs, IPlayerEvent +{ + /// + /// Max number of clipboard links that can be created with . + /// + public const int MaxClipboardCount = 3; + + private string[]? _clipboardTexts = null; + + /// + /// Initializes a new instance of the class. + /// + /// The instance of the player making the request. + /// The request arguments. + /// Whether the info being requested is sensitive. + /// The use to build the response. + public PlayerRequestedCustomRaInfoEventArgs( + CommandSender commandSender, + ArraySegment selectionArgs, + bool isSensitiveInfo, + StringBuilder infoBuilder) + { + Player = Player.Get(commandSender)!; + SelectedIdentifiers = selectionArgs.First().Split("."); + IsSensitiveInfo = isSensitiveInfo; + InfoBuilder = infoBuilder; + } + + /// + /// The player that made the request. + /// + public Player Player { get; } + + /// + /// Array of identifiers selected by the player. + /// Identifiers come from items in the RA player list that have been placed by plugins . + /// + public string[] SelectedIdentifiers { get; } + + /// + /// Gets whether the requested sensitive info. + /// + public bool IsSensitiveInfo { get; } + + /// + /// Gets the used to construct the response message. + /// + public StringBuilder InfoBuilder { get; } + + /// + /// Creates a clipboard link for the RA. + /// + /// + /// Usage ev.InfoBuilder.Append(ev.SetClipboardText("Click Me", "Text to copy to clipboard on click", 0));. + /// + /// Text to display as the link. + /// Text to copy to the clipboard when clicking on the link. + /// The id of the clipboard, must be between 0 and . + /// The formated clipboard link text. + /// Thown when id is not between 0 and . + public string SetClipboardText(string linkText, string clipboardText, byte id) + { + if (id >= MaxClipboardCount) + { + throw new ArgumentOutOfRangeException(nameof(id), id, $"id must be between 0 and {MaxClipboardCount}"); + } + + _clipboardTexts ??= new string[MaxClipboardCount]; + _clipboardTexts[id] = clipboardText; + + return $"{linkText}"; + } + + /// + /// Tries to get clipboard text for the specific id. + /// + /// The id associated with the clipboard text. + /// The found text, otherwise . + /// if set and not empty, otherwise . + /// Thown when id is not between 0 and . + public bool TryGetClipboardText(byte id, [NotNullWhen(true)] out string? text) + { + if (id >= MaxClipboardCount) + { + throw new ArgumentOutOfRangeException(nameof(id), id, $"id must be between 0 and {MaxClipboardCount}"); + } + + text = null; + + if (_clipboardTexts == null) + { + return false; + } + + text = _clipboardTexts[id]; + return !string.IsNullOrEmpty(text); + } + + private string LinkIdForClipboardId(byte id) => id switch + { + 0 => "CP_ID", + 1 => "CP_IP", + 2 => "CP_USERID", + _ => throw new ArgumentOutOfRangeException(nameof(id), id, $"id must be between 0 and {MaxClipboardCount}"), + }; +} diff --git a/LabApi/Events/Arguments/PlayerEvents/PlayerRequestedRaPlayerInfoEventArgs.cs b/LabApi/Events/Arguments/PlayerEvents/PlayerRequestedRaPlayerInfoEventArgs.cs new file mode 100644 index 00000000..2fe49664 --- /dev/null +++ b/LabApi/Events/Arguments/PlayerEvents/PlayerRequestedRaPlayerInfoEventArgs.cs @@ -0,0 +1,83 @@ +using LabApi.Events.Arguments.Interfaces; +using LabApi.Features.Wrappers; +using System; +using System.Text; + +namespace LabApi.Events.Arguments.PlayerEvents; + +/// +/// Represents the arguments for the event. +/// +public class PlayerRequestedRaPlayerInfoEventArgs : EventArgs, IPlayerEvent, ITargetEvent +{ + /// + /// Initializes a new instance of the class. + /// + /// The instance of the player making the request. + /// The component of the selected target. + /// Whether the info being requested is sensitive. + /// Whether the player has perms to view the user id of the target. + /// The used to construct the response message. + /// The used to construct the clipboard text of the targets player id. + /// The used to construct the clipboard text of the targets ip address. + /// The used to construct the clipboard text of the targets user id. + public PlayerRequestedRaPlayerInfoEventArgs( + CommandSender commandSender, + ReferenceHub targetHub, + bool isSensitiveInfo, + bool hasUserIdPerms, + StringBuilder infoBuilder, + StringBuilder idBuilder, + StringBuilder ipBuilder, + StringBuilder userIdBuilder) + { + Player = Player.Get(commandSender)!; + Target = Player.Get(targetHub); + IsSensitiveInfo = isSensitiveInfo; + HasUserIdPerms = hasUserIdPerms; + InfoBuilder = infoBuilder; + PlayerIdBuilder = idBuilder; + IpBuilder = ipBuilder; + UserIdBuilder = userIdBuilder; + } + + /// + /// The player that made the request. + /// + public Player Player { get; } + + /// + /// The target player selected. + /// + public Player Target { get; } + + /// + /// Whether the requested sensitive info. + /// + public bool IsSensitiveInfo { get; } + + /// + /// Whether the has permission to view the user id of the . + /// + public bool HasUserIdPerms { get; } + + /// + /// The used to construct the response message. + /// + public StringBuilder InfoBuilder { get; } + + /// + /// The used to construct the clipboard text of the targets player id. + /// + public StringBuilder PlayerIdBuilder { get; } + + /// + /// The used to construct the clipboard text of the targets ip address. + /// + public StringBuilder IpBuilder { get; } + + /// + /// The used to construct the clipboard text of the targets user id. + /// + public StringBuilder UserIdBuilder { get; } +} diff --git a/LabApi/Events/Arguments/PlayerEvents/PlayerRequestedRaPlayerListEventArgs.cs b/LabApi/Events/Arguments/PlayerEvents/PlayerRequestedRaPlayerListEventArgs.cs new file mode 100644 index 00000000..319ad882 --- /dev/null +++ b/LabApi/Events/Arguments/PlayerEvents/PlayerRequestedRaPlayerListEventArgs.cs @@ -0,0 +1,36 @@ +using LabApi.Events.Arguments.Interfaces; +using LabApi.Features.Wrappers; +using System; +using System.Text; + +namespace LabApi.Events.Arguments.PlayerEvents; + +/// +/// Represents the arguments for the event. +/// +public class PlayerRequestedRaPlayerListEventArgs : EventArgs, IPlayerEvent +{ + /// + /// Initializes a new instance of the class. + /// + /// The instance of the player that made the request for the RA player list. + /// The used to build the RA player list. + public PlayerRequestedRaPlayerListEventArgs(CommandSender commandSender, StringBuilder builder) + { + Player = Player.Get(commandSender)!; + ListBuilder = builder; + } + + /// + /// The player that requested the RA player list. + /// + public Player Player { get; } + + /// + /// The used to construct the RA player list. + /// + /// + /// String builder is not empty in this event and contains the RA list. + /// + public StringBuilder ListBuilder { get; } +} diff --git a/LabApi/Events/Arguments/PlayerEvents/PlayerRequestedRaPlayersInfoEventArgs.cs b/LabApi/Events/Arguments/PlayerEvents/PlayerRequestedRaPlayersInfoEventArgs.cs new file mode 100644 index 00000000..09c01901 --- /dev/null +++ b/LabApi/Events/Arguments/PlayerEvents/PlayerRequestedRaPlayersInfoEventArgs.cs @@ -0,0 +1,87 @@ +using LabApi.Events.Arguments.Interfaces; +using LabApi.Features.Wrappers; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; + +namespace LabApi.Events.Arguments.PlayerEvents; + +/// +/// Represents the arguments for the event. +/// +public class PlayerRequestedRaPlayersInfoEventArgs : EventArgs, IPlayerEvent +{ + private readonly IEnumerable _targets; + + /// + /// Initializes a new instance of the class. + /// + /// The instance of the player making the request. + /// The reference hub components of the targets selected in the request. + /// Whether the info being requested is sensitive. + /// Whether the player has perms to view the user ids of the targets. + /// The used to build the response. + /// The used to build the clipboard text for the targets ids. + /// The used to build the clipboard text for the targets IPs. + /// The used to build the clipboard text for the targets user ids. + public PlayerRequestedRaPlayersInfoEventArgs( + CommandSender commandSender, + IEnumerable targets, + bool isSensitiveInfo, + bool hasUserIdPerms, + StringBuilder infoBuilder, + StringBuilder idBuilder, + StringBuilder ipBuilder, + StringBuilder userIdBuilder) + { + Player = Player.Get(commandSender)!; + IsSensitiveInfo = isSensitiveInfo; + HasUserIdPerms = hasUserIdPerms; + InfoBuilder = infoBuilder; + PlayerIdBuilder = idBuilder; + IpBuilder = ipBuilder; + UserIdBuilder = userIdBuilder; + _targets = targets; + } + + /// + /// The player that made the request. + /// + public Player Player { get; } + + /// + /// The target players selected. + /// + public IEnumerable Targets => _targets.Select(Player.Get)!; + + /// + /// Gets whether the requested sensitive info. + /// + public bool IsSensitiveInfo { get; } + + /// + /// Gets whether the has perms to view the of the . + /// + public bool HasUserIdPerms { get; } + + /// + /// Gets the used to construct the response message. + /// + public StringBuilder InfoBuilder { get; } + + /// + /// Gets the used to construct the clipboard text for the . + /// + public StringBuilder PlayerIdBuilder { get; } + + /// + /// Gets the used to construct the clipboard text for the . + /// + public StringBuilder IpBuilder { get; } + + /// + /// Gets the used to construct the clipboard text for the . + /// + public StringBuilder UserIdBuilder { get; } +} diff --git a/LabApi/Events/Arguments/PlayerEvents/PlayerRequestingRaPlayerInfoEventArgs.cs b/LabApi/Events/Arguments/PlayerEvents/PlayerRequestingRaPlayerInfoEventArgs.cs new file mode 100644 index 00000000..2d43c423 --- /dev/null +++ b/LabApi/Events/Arguments/PlayerEvents/PlayerRequestingRaPlayerInfoEventArgs.cs @@ -0,0 +1,74 @@ +using LabApi.Events.Arguments.Interfaces; +using LabApi.Features.Wrappers; +using System; +using System.Text; + +namespace LabApi.Events.Arguments.PlayerEvents; + +/// +/// Represents the arguments for the event. +/// +public class PlayerRequestingRaPlayerInfoEventArgs : EventArgs, IPlayerEvent, ITargetEvent, ICancellableEvent +{ + /// + /// Initializes a new instance of the class. + /// + /// THe instance of the player making the request. + /// The component of the target player. + /// Whether the info being requested is sensitive. + /// Whether the player has perms to view sensitive info. + /// Whether the player has perms to view the targets user id. + /// The used to construct the response message. + public PlayerRequestingRaPlayerInfoEventArgs( + CommandSender commandSender, + ReferenceHub targetHub, + bool isSensitiveInfo, + bool hasSensitiveInfoPerms, + bool hasUserIdPerms, + StringBuilder infoBuilder) + { + Player = Player.Get(commandSender)!; + Target = Player.Get(targetHub); + IsSensitiveInfo = isSensitiveInfo; + HasSensitiveInfoPerms = hasSensitiveInfoPerms; + HasUserIdPerms = hasUserIdPerms; + InfoBuilder = infoBuilder; + IsAllowed = true; + } + + /// + /// The player than made the request. + /// + public Player Player { get; } + + /// + /// The target player selected. + /// + public Player Target { get; } + + /// + /// Gets or sets whether the player is requesting sensitive info. + /// + public bool IsSensitiveInfo { get; set; } + + /// + /// Gets or sets whether the player has permissions to view sensitive info. + /// + /// + /// If is and this is no response is sent. + /// + public bool HasSensitiveInfoPerms { get; set; } + + /// + /// Gets or sets whether the player has permission to view the . + /// + public bool HasUserIdPerms { get; set; } + + /// + /// The used to construct the response message. + /// + public StringBuilder InfoBuilder { get; } + + /// + public bool IsAllowed { get; set; } +} diff --git a/LabApi/Events/Arguments/PlayerEvents/PlayerRequestingRaPlayerListEventArgs.cs b/LabApi/Events/Arguments/PlayerEvents/PlayerRequestingRaPlayerListEventArgs.cs new file mode 100644 index 00000000..069f42e1 --- /dev/null +++ b/LabApi/Events/Arguments/PlayerEvents/PlayerRequestingRaPlayerListEventArgs.cs @@ -0,0 +1,75 @@ +using LabApi.Events.Arguments.Interfaces; +using LabApi.Features.Wrappers; +using System; +using System.Text; +using static RemoteAdmin.Communication.RaPlayerList; + +namespace LabApi.Events.Arguments.PlayerEvents; + +/// +/// Represents the arguments for the event. +/// +public class PlayerRequestingRaPlayerListEventArgs : EventArgs, IPlayerEvent, ICancellableEvent +{ + /// + /// Initializes a new instance of the class. + /// + /// The instance of the player that made the request for the RA player list. + /// The used to build the RA player list. + /// Whether to sort players by descending order. + /// The mode to use. + /// Whether the requester can view hidden local RA badges or not. + /// Whether the requester can view hidden global RA badges or not. + public PlayerRequestingRaPlayerListEventArgs( + CommandSender commandSender, + StringBuilder builder, + bool isDescending, + PlayerSorting sorting, + bool viewHiddenLocalBadges, + bool viewHiddenGlobalBadges) + { + Player = Player.Get(commandSender)!; + ListBuilder = builder; + IsDescending = isDescending; + Sorting = sorting; + ViewHiddenLocalBadges = viewHiddenLocalBadges; + ViewHiddenGlobalBadges = viewHiddenGlobalBadges; + IsAllowed = true; + } + + /// + /// The player that requested the RA player list. + /// + public Player Player { get; } + + /// + /// The used to construct the RA player list. + /// + /// + /// String builder is empty in this event. + /// + public StringBuilder ListBuilder { get; } + + /// + /// Gets or set whether to sort players by descending order. + /// + public bool IsDescending { get; set; } + + /// + /// Gets or sets the used. + /// + public PlayerSorting Sorting { get; set; } + + /// + /// Gets or sets whether the can view hidden local RA badges. + /// + public bool ViewHiddenLocalBadges { get; set; } + + /// + /// Gets or sets whether the can view hidden global RA badges. + /// + public bool ViewHiddenGlobalBadges { get; set; } + + /// + public bool IsAllowed { get; set; } +} diff --git a/LabApi/Events/Arguments/PlayerEvents/PlayerRequestingRaPlayersInfoEventArgs.cs b/LabApi/Events/Arguments/PlayerEvents/PlayerRequestingRaPlayersInfoEventArgs.cs new file mode 100644 index 00000000..f35da228 --- /dev/null +++ b/LabApi/Events/Arguments/PlayerEvents/PlayerRequestingRaPlayersInfoEventArgs.cs @@ -0,0 +1,78 @@ +using LabApi.Events.Arguments.Interfaces; +using LabApi.Features.Wrappers; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; + +namespace LabApi.Events.Arguments.PlayerEvents; + +/// +/// Represents the arguments for the event. +/// +public class PlayerRequestingRaPlayersInfoEventArgs : EventArgs, IPlayerEvent, ICancellableEvent +{ + private readonly IEnumerable _targets; + + /// + /// Initializes a new instance of the class. + /// + /// The instance of the player making the request. + /// The reference hub components of the targets selected by the player. + /// Whether the player requested sensitive info. + /// Whether the player has perms to view sensitive info. + /// Whether the player has perms to view the user ids of the targets. + /// The used to construct the response message. + public PlayerRequestingRaPlayersInfoEventArgs( + CommandSender commandSender, + IEnumerable targets, + bool isSensitiveInfo, + bool hasSensitiveInfoPerms, + bool hasUserIdPerms, + StringBuilder infoBuilder) + { + Player = Player.Get(commandSender)!; + IsSensitiveInfo = isSensitiveInfo; + HasSensitiveInfoPerms = hasSensitiveInfoPerms; + HasUserIdPerms = hasUserIdPerms; + InfoBuilder = infoBuilder; + IsAllowed = true; + _targets = targets; + } + + /// + /// The player that made the request. + /// + public Player Player { get; } + + /// + /// The target players selected. + /// + public IEnumerable Targets => _targets.Select(Player.Get)!; + + /// + /// Gets or sets whether the requested sensitive info. + /// + public bool IsSensitiveInfo { get; set; } + + /// + /// Gets or sets whether the player has permissions to view sensitive info. + /// + /// + /// If is and this is no response is sent. + /// + public bool HasSensitiveInfoPerms { get; set; } + + /// + /// Gets or sets whether the has permission to view the of the . + /// + public bool HasUserIdPerms { get; set; } + + /// + /// Gets the used to construct the response message. + /// + public StringBuilder InfoBuilder { get; } + + /// + public bool IsAllowed { get; set; } +} diff --git a/LabApi/Events/Arguments/PlayerEvents/PlayerRoomChangedEventArgs.cs b/LabApi/Events/Arguments/PlayerEvents/PlayerRoomChangedEventArgs.cs new file mode 100644 index 00000000..8dc27940 --- /dev/null +++ b/LabApi/Events/Arguments/PlayerEvents/PlayerRoomChangedEventArgs.cs @@ -0,0 +1,40 @@ +using LabApi.Events.Arguments.Interfaces; +using LabApi.Features.Wrappers; +using MapGeneration; +using System; + +namespace LabApi.Events.Arguments.PlayerEvents; + +/// +/// Represents the arguments for the event. +/// +public class PlayerRoomChangedEventArgs : EventArgs, IPlayerEvent +{ + /// + /// Initializes a new instance of the class. + /// + /// The player whose room changed. + /// The old room. + /// The new room. + public PlayerRoomChangedEventArgs(ReferenceHub player, RoomIdentifier oldRoom, RoomIdentifier newRoom) + { + Player = Player.Get(player); + OldRoom = Room.Get(oldRoom); + NewRoom = Room.Get(newRoom); + } + + /// + /// Gets the player whose last known room changed. + /// + public Player Player { get; } + + /// + /// Gets the old room. May be null if the player just spawned, went through void and such. + /// + public Room? OldRoom { get; } + + /// + /// Gets the new room. May be null if the player went into void, died and such. + /// + public Room? NewRoom { get; } +} diff --git a/LabApi/Events/Arguments/PlayerEvents/PlayerSearchToyAbortedEventArgs.cs b/LabApi/Events/Arguments/PlayerEvents/PlayerSearchToyAbortedEventArgs.cs index f411f07b..314ce292 100644 --- a/LabApi/Events/Arguments/PlayerEvents/PlayerSearchToyAbortedEventArgs.cs +++ b/LabApi/Events/Arguments/PlayerEvents/PlayerSearchToyAbortedEventArgs.cs @@ -13,11 +13,11 @@ public class PlayerSearchToyAbortedEventArgs : EventArgs, IPlayerEvent, IInterac /// /// Initializes a new instance for the class. /// - /// The player that canceled the search on the toy. + /// The player that canceled the search on the toy. /// The toy that was being searched. - public PlayerSearchToyAbortedEventArgs(ReferenceHub player, InvisibleInteractableToy toy) + public PlayerSearchToyAbortedEventArgs(ReferenceHub hub, InvisibleInteractableToy toy) { - Player = Player.Get(player); + Player = Player.Get(hub); Interactable = InteractableToy.Get(toy); } diff --git a/LabApi/Events/Arguments/PlayerEvents/PlayerSearchedAmmoEventArgs.cs b/LabApi/Events/Arguments/PlayerEvents/PlayerSearchedAmmoEventArgs.cs index 128adc66..430c46d3 100644 --- a/LabApi/Events/Arguments/PlayerEvents/PlayerSearchedAmmoEventArgs.cs +++ b/LabApi/Events/Arguments/PlayerEvents/PlayerSearchedAmmoEventArgs.cs @@ -13,11 +13,11 @@ public class PlayerSearchedAmmoEventArgs : EventArgs, IPlayerEvent, IAmmoPickupE /// /// Initializes a new instance of the class. /// - /// The player who searched for ammo pickup. + /// The player who searched for ammo pickup. /// The ammo pickup. - public PlayerSearchedAmmoEventArgs(ReferenceHub player, BaseAmmoPickup pickup) + public PlayerSearchedAmmoEventArgs(ReferenceHub hub, BaseAmmoPickup pickup) { - Player = Player.Get(player); + Player = Player.Get(hub); AmmoPickup = AmmoPickup.Get(pickup); } diff --git a/LabApi/Events/Arguments/PlayerEvents/PlayerSearchedArmorEventArgs.cs b/LabApi/Events/Arguments/PlayerEvents/PlayerSearchedArmorEventArgs.cs index 994d9456..9a2fc349 100644 --- a/LabApi/Events/Arguments/PlayerEvents/PlayerSearchedArmorEventArgs.cs +++ b/LabApi/Events/Arguments/PlayerEvents/PlayerSearchedArmorEventArgs.cs @@ -13,11 +13,11 @@ public class PlayerSearchedArmorEventArgs : EventArgs, IPlayerEvent, IBodyArmorP /// /// Initializes a new instance of the class. /// - /// The player who searched for armor pickup. + /// The player who searched for armor pickup. /// The armor pickup. - public PlayerSearchedArmorEventArgs(ReferenceHub player, BaseBodyArmorPickup pickup) + public PlayerSearchedArmorEventArgs(ReferenceHub hub, BaseBodyArmorPickup pickup) { - Player = Player.Get(player); + Player = Player.Get(hub); BodyArmorPickup = BodyArmorPickup.Get(pickup); } diff --git a/LabApi/Events/Arguments/PlayerEvents/PlayerSearchedPickupEventArgs.cs b/LabApi/Events/Arguments/PlayerEvents/PlayerSearchedPickupEventArgs.cs index 38755804..a2533a9f 100644 --- a/LabApi/Events/Arguments/PlayerEvents/PlayerSearchedPickupEventArgs.cs +++ b/LabApi/Events/Arguments/PlayerEvents/PlayerSearchedPickupEventArgs.cs @@ -13,11 +13,11 @@ public class PlayerSearchedPickupEventArgs : EventArgs, IPlayerEvent, IPickupEve /// /// Initializes a new instance of the class. /// - /// The player who searched for pickup. + /// The player who searched for pickup. /// The item pickup. - public PlayerSearchedPickupEventArgs(ReferenceHub player, ItemPickupBase pickup) + public PlayerSearchedPickupEventArgs(ReferenceHub hub, ItemPickupBase pickup) { - Player = Player.Get(player); + Player = Player.Get(hub); Pickup = Pickup.Get(pickup); } diff --git a/LabApi/Events/Arguments/PlayerEvents/PlayerSearchedToyEventArgs.cs b/LabApi/Events/Arguments/PlayerEvents/PlayerSearchedToyEventArgs.cs index 50ed12f0..38af42cc 100644 --- a/LabApi/Events/Arguments/PlayerEvents/PlayerSearchedToyEventArgs.cs +++ b/LabApi/Events/Arguments/PlayerEvents/PlayerSearchedToyEventArgs.cs @@ -13,11 +13,11 @@ public class PlayerSearchedToyEventArgs : EventArgs, IPlayerEvent, IInteractable /// /// Initializes a new instance of the class. /// - /// The player who searched the toy. + /// The player who searched the toy. /// The toy that was searched. - public PlayerSearchedToyEventArgs(ReferenceHub player, InvisibleInteractableToy toy) + public PlayerSearchedToyEventArgs(ReferenceHub hub, InvisibleInteractableToy toy) { - Player = Player.Get(player); + Player = Player.Get(hub); Interactable = InteractableToy.Get(toy); } diff --git a/LabApi/Events/Arguments/PlayerEvents/PlayerSearchingAmmoEventArgs.cs b/LabApi/Events/Arguments/PlayerEvents/PlayerSearchingAmmoEventArgs.cs index 665d3a28..ecc5545e 100644 --- a/LabApi/Events/Arguments/PlayerEvents/PlayerSearchingAmmoEventArgs.cs +++ b/LabApi/Events/Arguments/PlayerEvents/PlayerSearchingAmmoEventArgs.cs @@ -13,12 +13,12 @@ public class PlayerSearchingAmmoEventArgs : EventArgs, IPlayerEvent, IAmmoPickup /// /// Initializes a new instance of the class. /// - /// The player searching for ammo pickup. + /// The player searching for ammo pickup. /// The ammo pickup. - public PlayerSearchingAmmoEventArgs(ReferenceHub player, BaseAmmoPickup pickup) + public PlayerSearchingAmmoEventArgs(ReferenceHub hub, BaseAmmoPickup pickup) { IsAllowed = true; - Player = Player.Get(player); + Player = Player.Get(hub); AmmoPickup = AmmoPickup.Get(pickup); } diff --git a/LabApi/Events/Arguments/PlayerEvents/PlayerSearchingArmorEventArgs.cs b/LabApi/Events/Arguments/PlayerEvents/PlayerSearchingArmorEventArgs.cs index 7b921f4a..6d758e60 100644 --- a/LabApi/Events/Arguments/PlayerEvents/PlayerSearchingArmorEventArgs.cs +++ b/LabApi/Events/Arguments/PlayerEvents/PlayerSearchingArmorEventArgs.cs @@ -13,12 +13,12 @@ public class PlayerSearchingArmorEventArgs : EventArgs, IPlayerEvent, IBodyArmor /// /// Initializes a new instance of the class. /// - /// The player searching for armor. + /// The player searching for armor. /// The armor pickup. - public PlayerSearchingArmorEventArgs(ReferenceHub player, BaseBodyArmorPickup pickup) + public PlayerSearchingArmorEventArgs(ReferenceHub hub, BaseBodyArmorPickup pickup) { IsAllowed = true; - Player = Player.Get(player); + Player = Player.Get(hub); BodyArmorPickup = BodyArmorPickup.Get(pickup); } diff --git a/LabApi/Events/Arguments/PlayerEvents/PlayerSearchingPickupEventArgs.cs b/LabApi/Events/Arguments/PlayerEvents/PlayerSearchingPickupEventArgs.cs index dc12a500..de722ea4 100644 --- a/LabApi/Events/Arguments/PlayerEvents/PlayerSearchingPickupEventArgs.cs +++ b/LabApi/Events/Arguments/PlayerEvents/PlayerSearchingPickupEventArgs.cs @@ -13,12 +13,12 @@ public class PlayerSearchingPickupEventArgs : EventArgs, IPlayerEvent, IPickupEv /// /// Initializes a new instance of the class. /// - /// The player who is searching for the pickup. + /// The player who is searching for the pickup. /// The pickup being searched. - public PlayerSearchingPickupEventArgs(ReferenceHub player, ItemPickupBase pickup) + public PlayerSearchingPickupEventArgs(ReferenceHub hub, ItemPickupBase pickup) { IsAllowed = true; - Player = Player.Get(player); + Player = Player.Get(hub); Pickup = Pickup.Get(pickup); } diff --git a/LabApi/Events/Arguments/PlayerEvents/PlayerSearchingToyEventArgs.cs b/LabApi/Events/Arguments/PlayerEvents/PlayerSearchingToyEventArgs.cs index d6980cea..580c28b9 100644 --- a/LabApi/Events/Arguments/PlayerEvents/PlayerSearchingToyEventArgs.cs +++ b/LabApi/Events/Arguments/PlayerEvents/PlayerSearchingToyEventArgs.cs @@ -6,19 +6,19 @@ namespace LabApi.Events.Arguments.PlayerEvents; /// -/// Represents the arguments for the +/// Represents the arguments for the . /// public class PlayerSearchingToyEventArgs : EventArgs, IPlayerEvent, IInteractableEvent, ICancellableEvent { /// /// Initializes a new instance of the class. /// - /// The player who is searching the toy. + /// The player who is searching the toy. /// The toy that is going to be searched. - public PlayerSearchingToyEventArgs(ReferenceHub player, InvisibleInteractableToy toy) + public PlayerSearchingToyEventArgs(ReferenceHub hub, InvisibleInteractableToy toy) { IsAllowed = true; - Player = Player.Get(player); + Player = Player.Get(hub); Interactable = InteractableToy.Get(toy); } diff --git a/LabApi/Events/Arguments/PlayerEvents/PlayerSendingAttachmentsPrefsEventArgs.cs b/LabApi/Events/Arguments/PlayerEvents/PlayerSendingAttachmentsPrefsEventArgs.cs new file mode 100644 index 00000000..59bb8401 --- /dev/null +++ b/LabApi/Events/Arguments/PlayerEvents/PlayerSendingAttachmentsPrefsEventArgs.cs @@ -0,0 +1,48 @@ +using LabApi.Events.Arguments.Interfaces; +using LabApi.Features.Wrappers; +using System; + +namespace LabApi.Events.Arguments.PlayerEvents; + +/// +/// Represents the arguments for the event. +/// +public class PlayerSendingAttachmentsPrefsEventArgs : EventArgs, IPlayerEvent, ICancellableEvent +{ + /// + /// Initialized a new instance of . + /// + /// The player who is changing the firearm attachments. + /// The firearm type whose attachments preferences are being changed. + /// The old attachments code. + /// The new attachments code requested by the player. + public PlayerSendingAttachmentsPrefsEventArgs(ReferenceHub player, ItemType firearm, uint oldAttachments, uint newAttachments) + { + Player = Player.Get(player); + FirearmType = firearm; + OldAttachments = oldAttachments; + NewAttachments = newAttachments; + IsAllowed = true; + } + + /// + public Player Player { get; } + + /// + /// Gets the of the firearm. + /// + public ItemType FirearmType { get; set; } + + /// + /// Gets previous attachments code stored on the server. + /// + public uint OldAttachments { get; } + + /// + /// Gets or sets new attachments code. Edited values are NOT propagated back to the client and are stored on the server for on-spawn purposes. + /// + public uint NewAttachments { get; set; } + + /// + public bool IsAllowed { get; set; } +} diff --git a/LabApi/Events/Arguments/PlayerEvents/PlayerSendingHitmarkerEventArgs.cs b/LabApi/Events/Arguments/PlayerEvents/PlayerSendingHitmarkerEventArgs.cs new file mode 100644 index 00000000..cfca9f8f --- /dev/null +++ b/LabApi/Events/Arguments/PlayerEvents/PlayerSendingHitmarkerEventArgs.cs @@ -0,0 +1,44 @@ +using LabApi.Events.Arguments.Interfaces; +using LabApi.Features.Wrappers; +using System; + +namespace LabApi.Events.Arguments.PlayerEvents; + +/// +/// Represents the arguments for the event. +/// +public class PlayerSendingHitmarkerEventArgs : EventArgs, IPlayerEvent, ICancellableEvent +{ + /// + /// Initializes a new instance for the class. + /// + /// The player that is sending the hitmarker. + /// The target size multiplier. + /// Whether the hitmarker sound effect should play. + public PlayerSendingHitmarkerEventArgs(ReferenceHub hub, float size, bool playAudio) + { + Player = Player.Get(hub); + Size = size; + PlayAudio = playAudio; + + IsAllowed = true; + } + + /// + /// Gets or sets the player that the hitmarker is being sent to. + /// + public Player Player { get; set; } + + /// + /// Gets or sets the target size multiplier. + /// + public float Size { get; set; } + + /// + /// Gets or sets a value indicating whether the hitmarker sound effect should play. + /// + public bool PlayAudio { get; set; } + + /// + public bool IsAllowed { get; set; } +} diff --git a/LabApi/Events/Arguments/PlayerEvents/PlayerSendingVoiceMessageEventArgs.cs b/LabApi/Events/Arguments/PlayerEvents/PlayerSendingVoiceMessageEventArgs.cs index 30652ee1..883973c9 100644 --- a/LabApi/Events/Arguments/PlayerEvents/PlayerSendingVoiceMessageEventArgs.cs +++ b/LabApi/Events/Arguments/PlayerEvents/PlayerSendingVoiceMessageEventArgs.cs @@ -10,6 +10,8 @@ namespace LabApi.Events.Arguments.PlayerEvents; /// public class PlayerSendingVoiceMessageEventArgs : EventArgs, ICancellableEvent, IPlayerEvent, IVoiceMessageEvent { + private VoiceMessage _message; + /// /// Initializes a new instance of the class. /// @@ -39,6 +41,4 @@ public PlayerSendingVoiceMessageEventArgs(ref VoiceMessage message) /// this will be ignored. /// public bool IsAllowed { get; set; } - - private VoiceMessage _message; } \ No newline at end of file diff --git a/LabApi/Events/Arguments/PlayerEvents/PlayerSentAttachmentsPrefsEventArgs.cs b/LabApi/Events/Arguments/PlayerEvents/PlayerSentAttachmentsPrefsEventArgs.cs new file mode 100644 index 00000000..0afd29cd --- /dev/null +++ b/LabApi/Events/Arguments/PlayerEvents/PlayerSentAttachmentsPrefsEventArgs.cs @@ -0,0 +1,44 @@ +using LabApi.Events.Arguments.Interfaces; +using LabApi.Features.Wrappers; +using System; + +namespace LabApi.Events.Arguments.PlayerEvents; + +/// +/// Represents the arguments for the event. +/// +public class PlayerSentAttachmentsPrefsEventArgs : EventArgs, IPlayerEvent +{ + /// + /// Initialized a new instance of . + /// + /// The player who is changing the firearm attachments. + /// The firearm type whose attachments preferences are being changed. + /// The old attachments code. + /// The new attachments code. + public PlayerSentAttachmentsPrefsEventArgs(ReferenceHub player, ItemType firearm, uint oldAttachments, uint newAttachments) + { + Player = Player.Get(player); + FirearmType = firearm; + OldAttachments = oldAttachments; + NewAttachments = newAttachments; + } + + /// + public Player Player { get; } + + /// + /// The of the firearm. + /// + public ItemType FirearmType { get; } + + /// + /// Gets previous attachments code stored on the server. + /// + public uint OldAttachments { get; } + + /// + /// Gets the new attachments code stored on the server. + /// + public uint NewAttachments { get; } +} diff --git a/LabApi/Events/Arguments/PlayerEvents/PlayerSentHitmarkerEventArgs.cs b/LabApi/Events/Arguments/PlayerEvents/PlayerSentHitmarkerEventArgs.cs new file mode 100644 index 00000000..0532502b --- /dev/null +++ b/LabApi/Events/Arguments/PlayerEvents/PlayerSentHitmarkerEventArgs.cs @@ -0,0 +1,39 @@ +using LabApi.Events.Arguments.Interfaces; +using LabApi.Features.Wrappers; +using System; + +namespace LabApi.Events.Arguments.PlayerEvents; + +/// +/// Represents the arguments for the event. +/// +public class PlayerSentHitmarkerEventArgs : EventArgs, IPlayerEvent +{ + /// + /// Initializes a new instance for the class. + /// + /// The player that sent the hitmarker. + /// The target size multiplier. + /// Whether the hitmarker sound effect was played. + public PlayerSentHitmarkerEventArgs(ReferenceHub hub, float size, bool playedAudio) + { + Player = Player.Get(hub); + Size = size; + PlayedAudio = playedAudio; + } + + /// + /// Gets the player that the hitmarker was sent to. + /// + public Player Player { get; } + + /// + /// Gets the target size multiplier. + /// + public float Size { get; } + + /// + /// Gets a value indicating whether the hitmarker sound effect was played. + /// + public bool PlayedAudio { get; } +} diff --git a/LabApi/Events/Arguments/PlayerEvents/PlayerShootingWeaponEventArgs.cs b/LabApi/Events/Arguments/PlayerEvents/PlayerShootingWeaponEventArgs.cs index 28047a03..859a667a 100644 --- a/LabApi/Events/Arguments/PlayerEvents/PlayerShootingWeaponEventArgs.cs +++ b/LabApi/Events/Arguments/PlayerEvents/PlayerShootingWeaponEventArgs.cs @@ -13,12 +13,12 @@ public class PlayerShootingWeaponEventArgs : EventArgs, IPlayerEvent, IFirearmIt /// /// Initializes a new instance of the class. /// - /// The player who is shooting. + /// The player who is shooting. /// The firearm that the player shooting from. - public PlayerShootingWeaponEventArgs(ReferenceHub player, Firearm weapon) + public PlayerShootingWeaponEventArgs(ReferenceHub hub, Firearm weapon) { IsAllowed = true; - Player = Player.Get(player); + Player = Player.Get(hub); FirearmItem = FirearmItem.Get(weapon); } diff --git a/LabApi/Events/Arguments/PlayerEvents/PlayerShotWeaponEventArgs.cs b/LabApi/Events/Arguments/PlayerEvents/PlayerShotWeaponEventArgs.cs index f502c47f..7d0e31dd 100644 --- a/LabApi/Events/Arguments/PlayerEvents/PlayerShotWeaponEventArgs.cs +++ b/LabApi/Events/Arguments/PlayerEvents/PlayerShotWeaponEventArgs.cs @@ -13,11 +13,11 @@ public class PlayerShotWeaponEventArgs : EventArgs, IPlayerEvent, IFirearmItemEv /// /// Initializes a new instance of the class. /// - /// The player who shot. + /// The player who shot. /// The firearm that the player shot from. - public PlayerShotWeaponEventArgs(ReferenceHub player, Firearm weapon) + public PlayerShotWeaponEventArgs(ReferenceHub hub, Firearm weapon) { - Player = Player.Get(player); + Player = Player.Get(hub); FirearmItem = FirearmItem.Get(weapon); } diff --git a/LabApi/Events/Arguments/PlayerEvents/PlayerSpawnedEventArgs.cs b/LabApi/Events/Arguments/PlayerEvents/PlayerSpawnedEventArgs.cs index 5196b166..d899d140 100644 --- a/LabApi/Events/Arguments/PlayerEvents/PlayerSpawnedEventArgs.cs +++ b/LabApi/Events/Arguments/PlayerEvents/PlayerSpawnedEventArgs.cs @@ -14,14 +14,14 @@ public class PlayerSpawnedEventArgs : EventArgs, IPlayerEvent /// /// Initializes a new instance of the class. /// - /// The player who is being spawned. + /// The player who is being spawned. /// The role that is being applied. /// If spawnpoint should be used. /// The default spawn location. /// The default spawn horizontal rotation. - public PlayerSpawnedEventArgs(ReferenceHub player, PlayerRoleBase role, bool useSpawnPoint, Vector3 spawnLocation, float horizontalRotation) + public PlayerSpawnedEventArgs(ReferenceHub hub, PlayerRoleBase role, bool useSpawnPoint, Vector3 spawnLocation, float horizontalRotation) { - Player = Player.Get(player); + Player = Player.Get(hub); Role = role; UseSpawnPoint = useSpawnPoint; SpawnLocation = spawnLocation; diff --git a/LabApi/Events/Arguments/PlayerEvents/PlayerSpawnedRagdollEventArgs.cs b/LabApi/Events/Arguments/PlayerEvents/PlayerSpawnedRagdollEventArgs.cs index 7ccd0b9f..a5a88f48 100644 --- a/LabApi/Events/Arguments/PlayerEvents/PlayerSpawnedRagdollEventArgs.cs +++ b/LabApi/Events/Arguments/PlayerEvents/PlayerSpawnedRagdollEventArgs.cs @@ -14,12 +14,12 @@ public class PlayerSpawnedRagdollEventArgs : EventArgs, IPlayerEvent, IRagdollEv /// /// Initializes a new instance of the class. /// - /// The player from who is ragdoll from. + /// The player from who is ragdoll from. /// The spawned ragdoll. /// The damage handler that caused the death of the player. - public PlayerSpawnedRagdollEventArgs(ReferenceHub player, BasicRagdoll ragdoll, DamageHandlerBase damageHandler) + public PlayerSpawnedRagdollEventArgs(ReferenceHub hub, BasicRagdoll ragdoll, DamageHandlerBase damageHandler) { - Player = Player.Get(player); + Player = Player.Get(hub); Ragdoll = Ragdoll.Get(ragdoll); DamageHandler = damageHandler; } diff --git a/LabApi/Events/Arguments/PlayerEvents/PlayerSpawningEventArgs.cs b/LabApi/Events/Arguments/PlayerEvents/PlayerSpawningEventArgs.cs index ba75ad34..7e023899 100644 --- a/LabApi/Events/Arguments/PlayerEvents/PlayerSpawningEventArgs.cs +++ b/LabApi/Events/Arguments/PlayerEvents/PlayerSpawningEventArgs.cs @@ -11,21 +11,21 @@ namespace LabApi.Events.Arguments.PlayerEvents; /// public class PlayerSpawningEventArgs : EventArgs, IPlayerEvent, ICancellableEvent { - Vector3 _spawnLocation; - float _horizontalRotation; + private Vector3 _spawnLocation; + private float _horizontalRotation; /// /// Initializes a new instance of the class. /// - /// The player who is being spawned. + /// The player who is being spawned. /// The role that is being applied. /// If spawnpoint should be used. /// The default spawn location. /// The default spawn horizontal rotation. - public PlayerSpawningEventArgs(ReferenceHub player, PlayerRoleBase role, bool useSpawnPoint, Vector3 spawnLocation, float horizontalRotation) + public PlayerSpawningEventArgs(ReferenceHub hub, PlayerRoleBase role, bool useSpawnPoint, Vector3 spawnLocation, float horizontalRotation) { IsAllowed = true; - Player = Player.Get(player); + Player = Player.Get(hub); Role = role; UseSpawnPoint = useSpawnPoint; _spawnLocation = spawnLocation; diff --git a/LabApi/Events/Arguments/PlayerEvents/PlayerSpawningRagdollEventArgs.cs b/LabApi/Events/Arguments/PlayerEvents/PlayerSpawningRagdollEventArgs.cs index 811263ee..b756b921 100644 --- a/LabApi/Events/Arguments/PlayerEvents/PlayerSpawningRagdollEventArgs.cs +++ b/LabApi/Events/Arguments/PlayerEvents/PlayerSpawningRagdollEventArgs.cs @@ -9,19 +9,19 @@ namespace LabApi.Events.Arguments.PlayerEvents; /// /// Represents the arguments for the event. /// -public class PlayerSpawningRagdollEventArgs : EventArgs, IPlayerEvent, IRagdollEvent, ICancellableEvent +public class PlayerSpawningRagdollEventArgs : EventArgs, IPlayerEvent, ICancellableEvent { /// /// Initializes a new instance of the class. /// - /// The player from who is ragdoll from. + /// The player from who is ragdoll from. /// The ragdoll which being spawned. /// The damage handler that caused the death of the player. - public PlayerSpawningRagdollEventArgs(ReferenceHub player, BasicRagdoll ragdoll, DamageHandlerBase damageHandler) + public PlayerSpawningRagdollEventArgs(ReferenceHub hub, BasicRagdoll ragdoll, DamageHandlerBase damageHandler) { IsAllowed = true; - Player = Player.Get(player); - Ragdoll = Ragdoll.Get(ragdoll); + Player = Player.Get(hub); + RagdollPrefab = Ragdoll.Get(ragdoll); DamageHandler = damageHandler; } @@ -31,9 +31,15 @@ public PlayerSpawningRagdollEventArgs(ReferenceHub player, BasicRagdoll ragdoll, public Player Player { get; } /// - /// Gets the ragdoll which being spawned. + /// Gets the ragdoll prefab which will be used to instantiate the ragdoll. /// - public Ragdoll Ragdoll { get; } + [Obsolete($"use {nameof(RagdollPrefab)} instead.")] + public Ragdoll Ragdoll => RagdollPrefab; + + /// + /// Gets the ragdoll prefab which will be used to instantiate the ragdoll. + /// + public Ragdoll RagdollPrefab { get; } /// /// Gets the damage handler that caused the death of the player. diff --git a/LabApi/Events/Arguments/PlayerEvents/PlayerSpinnedRevolverEventArgs.cs b/LabApi/Events/Arguments/PlayerEvents/PlayerSpinnedRevolverEventArgs.cs new file mode 100644 index 00000000..89fbaae8 --- /dev/null +++ b/LabApi/Events/Arguments/PlayerEvents/PlayerSpinnedRevolverEventArgs.cs @@ -0,0 +1,33 @@ +using InventorySystem.Items.Firearms; +using LabApi.Events.Arguments.Interfaces; +using LabApi.Features.Wrappers; +using System; + +namespace LabApi.Events.Arguments.PlayerEvents; + +/// +/// Represents the arguments for the event. +/// +public class PlayerSpinnedRevolverEventArgs : EventArgs, IPlayerEvent, IRevolverItemEvent +{ + /// + /// Initializes a new instance of the class. + /// + /// The player who spinned the revolver. + /// The revolver firearm. + public PlayerSpinnedRevolverEventArgs(ReferenceHub hub, Firearm weapon) + { + Player = Player.Get(hub); + Revolver = (RevolverFirearm)FirearmItem.Get(weapon); + } + + /// + /// Gets the player who spinned the revolver. + /// + public Player Player { get; } + + /// + /// Gets the revolver item. + /// + public RevolverFirearm Revolver { get; } +} diff --git a/LabApi/Events/Arguments/PlayerEvents/PlayerSpinningRevolverEventArgs.cs b/LabApi/Events/Arguments/PlayerEvents/PlayerSpinningRevolverEventArgs.cs new file mode 100644 index 00000000..4fd37a6c --- /dev/null +++ b/LabApi/Events/Arguments/PlayerEvents/PlayerSpinningRevolverEventArgs.cs @@ -0,0 +1,37 @@ +using InventorySystem.Items.Firearms; +using LabApi.Events.Arguments.Interfaces; +using LabApi.Features.Wrappers; +using System; + +namespace LabApi.Events.Arguments.PlayerEvents; + +/// +/// Represents the arguments for the event. +/// +public class PlayerSpinningRevolverEventArgs : EventArgs, IPlayerEvent, IRevolverItemEvent, ICancellableEvent +{ + /// + /// Initializes a new instance of the class. + /// + /// The player who is attempting to spin the revolver. + /// The revolver firearm. + public PlayerSpinningRevolverEventArgs(ReferenceHub hub, Firearm weapon) + { + Player = Player.Get(hub); + Revolver = (RevolverFirearm)FirearmItem.Get(weapon); + IsAllowed = true; + } + + /// + /// Gets the player who is attempting to spin the revolver. + /// + public Player Player { get; } + + /// + /// Gets the revolver item. + /// + public RevolverFirearm Revolver { get; } + + /// + public bool IsAllowed { get; set; } +} diff --git a/LabApi/Events/Arguments/PlayerEvents/PlayerThrewItemEventArgs.cs b/LabApi/Events/Arguments/PlayerEvents/PlayerThrewItemEventArgs.cs index 57d8fea4..45030a8d 100644 --- a/LabApi/Events/Arguments/PlayerEvents/PlayerThrewItemEventArgs.cs +++ b/LabApi/Events/Arguments/PlayerEvents/PlayerThrewItemEventArgs.cs @@ -14,12 +14,12 @@ public class PlayerThrewItemEventArgs : EventArgs, IPlayerEvent, IPickupEvent /// /// Initializes a new instance of the class. /// - /// The player who threw the item. + /// The player who threw the item. /// The item that was thrown. /// The rigidbody of the item. - public PlayerThrewItemEventArgs(ReferenceHub player, ItemPickupBase item, Rigidbody rigidbody) + public PlayerThrewItemEventArgs(ReferenceHub hub, ItemPickupBase item, Rigidbody rigidbody) { - Player = Player.Get(player); + Player = Player.Get(hub); Pickup = Pickup.Get(item); Rigidbody = rigidbody; } diff --git a/LabApi/Events/Arguments/PlayerEvents/PlayerThrewProjectileEventArgs.cs b/LabApi/Events/Arguments/PlayerEvents/PlayerThrewProjectileEventArgs.cs index 7b048f8d..e683b115 100644 --- a/LabApi/Events/Arguments/PlayerEvents/PlayerThrewProjectileEventArgs.cs +++ b/LabApi/Events/Arguments/PlayerEvents/PlayerThrewProjectileEventArgs.cs @@ -15,14 +15,14 @@ public class PlayerThrewProjectileEventArgs : EventArgs, IPlayerEvent, IThrowabl /// /// Initializes a new instance of the class. /// - /// The player who threw the throwable item. + /// The player who threw the throwable item. /// The original item that was thrown. /// The new projectile object created. /// Projectile settings at which throwable was thrown. /// Value whenever the throwable was thrown at full force (overhand). - public PlayerThrewProjectileEventArgs(ReferenceHub player, BaseThrowableItem item, ThrownProjectile projectile, ProjectileSettings projectileSettings, bool fullForce) + public PlayerThrewProjectileEventArgs(ReferenceHub hub, BaseThrowableItem item, ThrownProjectile projectile, ProjectileSettings projectileSettings, bool fullForce) { - Player = Player.Get(player); + Player = Player.Get(hub); ThrowableItem = ThrowableItem.Get(item); Projectile = Projectile.Get(projectile); ProjectileSettings = projectileSettings; diff --git a/LabApi/Events/Arguments/PlayerEvents/PlayerThrowingItemEventArgs.cs b/LabApi/Events/Arguments/PlayerEvents/PlayerThrowingItemEventArgs.cs index 03c518fc..f44c6f5e 100644 --- a/LabApi/Events/Arguments/PlayerEvents/PlayerThrowingItemEventArgs.cs +++ b/LabApi/Events/Arguments/PlayerEvents/PlayerThrowingItemEventArgs.cs @@ -1,5 +1,4 @@ -using InventorySystem.Items; -using InventorySystem.Items.Pickups; +using InventorySystem.Items.Pickups; using LabApi.Events.Arguments.Interfaces; using LabApi.Features.Wrappers; using System; @@ -15,13 +14,13 @@ public class PlayerThrowingItemEventArgs : EventArgs, IPlayerEvent, IPickupEvent /// /// Initializes a new instance of the class. /// - /// The player who is throwing the item. + /// The player who is throwing the item. /// The item that is being thrown. /// The rigidbody of the item. - public PlayerThrowingItemEventArgs(ReferenceHub player, ItemPickupBase item, Rigidbody rigidbody) + public PlayerThrowingItemEventArgs(ReferenceHub hub, ItemPickupBase item, Rigidbody rigidbody) { IsAllowed = true; - Player = Player.Get(player); + Player = Player.Get(hub); Pickup = Pickup.Get(item); Rigidbody = rigidbody; } diff --git a/LabApi/Events/Arguments/PlayerEvents/PlayerThrowingProjectileEventArgs.cs b/LabApi/Events/Arguments/PlayerEvents/PlayerThrowingProjectileEventArgs.cs index f33134bc..f25c7dcb 100644 --- a/LabApi/Events/Arguments/PlayerEvents/PlayerThrowingProjectileEventArgs.cs +++ b/LabApi/Events/Arguments/PlayerEvents/PlayerThrowingProjectileEventArgs.cs @@ -14,14 +14,14 @@ public class PlayerThrowingProjectileEventArgs : EventArgs, IPlayerEvent, IThrow /// /// Initializes a new instance of the class. /// - /// The player who threw the projectile. + /// The player who threw the projectile. /// The original throwable item. /// Projectile settings at which is throwable being thrown. /// Value whenever the throwable is being thrown at full force (overhand). - public PlayerThrowingProjectileEventArgs(ReferenceHub player, BaseThrowableItem item, ProjectileSettings projectileSettings, bool fullForce) + public PlayerThrowingProjectileEventArgs(ReferenceHub hub, BaseThrowableItem item, ProjectileSettings projectileSettings, bool fullForce) { IsAllowed = true; - Player = Player.Get(player); + Player = Player.Get(hub); ThrowableItem = ThrowableItem.Get(item); ProjectileSettings = projectileSettings; FullForce = fullForce; diff --git a/LabApi/Events/Arguments/PlayerEvents/PlayerToggledDisruptorFiringModeEventArgs.cs b/LabApi/Events/Arguments/PlayerEvents/PlayerToggledDisruptorFiringModeEventArgs.cs new file mode 100644 index 00000000..12b23419 --- /dev/null +++ b/LabApi/Events/Arguments/PlayerEvents/PlayerToggledDisruptorFiringModeEventArgs.cs @@ -0,0 +1,40 @@ +using InventorySystem.Items.Firearms; +using LabApi.Events.Arguments.Interfaces; +using LabApi.Features.Wrappers; +using System; + +namespace LabApi.Events.Arguments.PlayerEvents; + +/// +/// Represents the arguments for the event. +/// +public class PlayerToggledDisruptorFiringModeEventArgs : EventArgs, IPlayerEvent, IFirearmItemEvent +{ + /// + /// Initializes a new instance of the class. + /// + /// The player who toggled the firing mode. + /// The weapon that the player toggled. + /// Whether the mode is now single shot. + public PlayerToggledDisruptorFiringModeEventArgs(ReferenceHub hub, Firearm weapon, bool singleShot) + { + Player = Player.Get(hub); + FirearmItem = FirearmItem.Get(weapon); + SingleShotMode = singleShot; + } + + /// + /// Gets the player who toggled the firing mode. + /// + public Player Player { get; } + + /// + /// Gets the weapon that the player toggled. + /// + public FirearmItem FirearmItem { get; } + + /// + /// Gets whether the disruptor is in single shot mode. + /// + public bool SingleShotMode { get; } +} diff --git a/LabApi/Events/Arguments/PlayerEvents/PlayerToggledFlashlightEventArgs.cs b/LabApi/Events/Arguments/PlayerEvents/PlayerToggledFlashlightEventArgs.cs index 57bb3d14..90157e53 100644 --- a/LabApi/Events/Arguments/PlayerEvents/PlayerToggledFlashlightEventArgs.cs +++ b/LabApi/Events/Arguments/PlayerEvents/PlayerToggledFlashlightEventArgs.cs @@ -13,12 +13,12 @@ public class PlayerToggledFlashlightEventArgs : EventArgs, IPlayerEvent, ILightI /// /// Initializes a new instance of the class. /// - /// The player who toggled the flashlight. + /// The player who toggled the flashlight. /// The flashlight item. /// New state of the flashlight. - public PlayerToggledFlashlightEventArgs(ReferenceHub player, ToggleableLightItemBase item, bool newState) + public PlayerToggledFlashlightEventArgs(ReferenceHub hub, ToggleableLightItemBase item, bool newState) { - Player = Player.Get(player); + Player = Player.Get(hub); LightItem = LightItem.Get(item); NewState = newState; } diff --git a/LabApi/Events/Arguments/PlayerEvents/PlayerToggledNoclipEventArgs.cs b/LabApi/Events/Arguments/PlayerEvents/PlayerToggledNoclipEventArgs.cs index a7a438bd..719aa00d 100644 --- a/LabApi/Events/Arguments/PlayerEvents/PlayerToggledNoclipEventArgs.cs +++ b/LabApi/Events/Arguments/PlayerEvents/PlayerToggledNoclipEventArgs.cs @@ -2,32 +2,31 @@ using LabApi.Features.Wrappers; using System; -namespace LabApi.Events.Arguments.PlayerEvents +namespace LabApi.Events.Arguments.PlayerEvents; + +/// +/// Represents the arguments for the event. +/// +public class PlayerToggledNoclipEventArgs : EventArgs, IPlayerEvent { /// - /// Represents the arguments for the event. + /// Initializes a new instance of the class. /// - public class PlayerToggledNoclipEventArgs : EventArgs, IPlayerEvent + /// The player who has toggled the noclip. + /// The new state of the noclip. + public PlayerToggledNoclipEventArgs(ReferenceHub hub, bool isNoclipping) { - /// - /// Initializes a new instance of the class. - /// - /// The player who has toggled the noclip. - /// The new state of the noclip. - public PlayerToggledNoclipEventArgs(ReferenceHub player, bool isNoclipping) - { - Player = Player.Get(player); - IsNoclipping = isNoclipping; - } + Player = Player.Get(hub); + IsNoclipping = isNoclipping; + } - /// - /// Gets the player who toggled noclip. - /// - public Player Player { get; } + /// + /// Gets the player who toggled noclip. + /// + public Player Player { get; } - /// - /// Gets whether the player now has noclip enabled or not. - /// - public bool IsNoclipping { get; } - } + /// + /// Gets whether the player now has noclip enabled or not. + /// + public bool IsNoclipping { get; } } diff --git a/LabApi/Events/Arguments/PlayerEvents/PlayerToggledRadioEventArgs.cs b/LabApi/Events/Arguments/PlayerEvents/PlayerToggledRadioEventArgs.cs index 8fd0ca4a..2e9f0ea4 100644 --- a/LabApi/Events/Arguments/PlayerEvents/PlayerToggledRadioEventArgs.cs +++ b/LabApi/Events/Arguments/PlayerEvents/PlayerToggledRadioEventArgs.cs @@ -13,12 +13,12 @@ public class PlayerToggledRadioEventArgs : EventArgs, IPlayerEvent, IRadioItemEv /// /// Initializes a new instance of the class. /// - /// The player who toggled the radio. + /// The player who toggled the radio. /// The radio item. /// New state of the radio. - public PlayerToggledRadioEventArgs(ReferenceHub player, BaseRadioItem radio, bool newState) + public PlayerToggledRadioEventArgs(ReferenceHub hub, BaseRadioItem radio, bool newState) { - Player = Player.Get(player); + Player = Player.Get(hub); RadioItem = RadioItem.Get(radio); NewState = newState; } diff --git a/LabApi/Events/Arguments/PlayerEvents/PlayerToggledWeaponFlashlightEventArgs.cs b/LabApi/Events/Arguments/PlayerEvents/PlayerToggledWeaponFlashlightEventArgs.cs index 2839f9e9..2c11ed2d 100644 --- a/LabApi/Events/Arguments/PlayerEvents/PlayerToggledWeaponFlashlightEventArgs.cs +++ b/LabApi/Events/Arguments/PlayerEvents/PlayerToggledWeaponFlashlightEventArgs.cs @@ -13,12 +13,12 @@ public class PlayerToggledWeaponFlashlightEventArgs : EventArgs, IPlayerEvent, I /// /// Initializes a new instance of the class. /// - /// The player who toggled the flashlight. + /// The player who toggled the flashlight. /// The flashlight item. /// The new state of the flashlight. - public PlayerToggledWeaponFlashlightEventArgs(ReferenceHub player, Firearm item, bool newState) + public PlayerToggledWeaponFlashlightEventArgs(ReferenceHub hub, Firearm item, bool newState) { - Player = Player.Get(player); + Player = Player.Get(hub); FirearmItem = FirearmItem.Get(item); NewState = newState; } diff --git a/LabApi/Events/Arguments/PlayerEvents/PlayerTogglingFlashlightEventArgs.cs b/LabApi/Events/Arguments/PlayerEvents/PlayerTogglingFlashlightEventArgs.cs index 31612324..08d792d2 100644 --- a/LabApi/Events/Arguments/PlayerEvents/PlayerTogglingFlashlightEventArgs.cs +++ b/LabApi/Events/Arguments/PlayerEvents/PlayerTogglingFlashlightEventArgs.cs @@ -13,13 +13,13 @@ public class PlayerTogglingFlashlightEventArgs : EventArgs, IPlayerEvent, ILight /// /// Initializes a new instance of the class. /// - /// The player who is toggling the flashlight. + /// The player who is toggling the flashlight. /// The flashlight that is being toggled. /// Whenever the flashlight is being toggled to on or off state. - public PlayerTogglingFlashlightEventArgs(ReferenceHub player, ToggleableLightItemBase item, bool newState) + public PlayerTogglingFlashlightEventArgs(ReferenceHub hub, ToggleableLightItemBase item, bool newState) { IsAllowed = true; - Player = Player.Get(player); + Player = Player.Get(hub); LightItem = LightItem.Get(item); NewState = newState; } diff --git a/LabApi/Events/Arguments/PlayerEvents/PlayerTogglingNoclipEventArgs.cs b/LabApi/Events/Arguments/PlayerEvents/PlayerTogglingNoclipEventArgs.cs index 3257e209..1f47f831 100644 --- a/LabApi/Events/Arguments/PlayerEvents/PlayerTogglingNoclipEventArgs.cs +++ b/LabApi/Events/Arguments/PlayerEvents/PlayerTogglingNoclipEventArgs.cs @@ -10,14 +10,14 @@ namespace LabApi.Events.Arguments.PlayerEvents; public class PlayerTogglingNoclipEventArgs : EventArgs, IPlayerEvent, ICancellableEvent { /// - /// Initializes a new instance of clas. + /// Initializes a new instance of class. /// - /// The player who is attempting to toggle noclip. + /// The player who is attempting to toggle noclip. /// Whether the noclip state will be enabled or disabled. - public PlayerTogglingNoclipEventArgs(ReferenceHub player, bool newState) + public PlayerTogglingNoclipEventArgs(ReferenceHub hub, bool newState) { IsAllowed = true; - Player = Player.Get(player); + Player = Player.Get(hub); NewNoclipState = newState; } diff --git a/LabApi/Events/Arguments/PlayerEvents/PlayerTogglingRadioEventArgs.cs b/LabApi/Events/Arguments/PlayerEvents/PlayerTogglingRadioEventArgs.cs index 66a25d46..93d0d11c 100644 --- a/LabApi/Events/Arguments/PlayerEvents/PlayerTogglingRadioEventArgs.cs +++ b/LabApi/Events/Arguments/PlayerEvents/PlayerTogglingRadioEventArgs.cs @@ -13,13 +13,13 @@ public class PlayerTogglingRadioEventArgs : EventArgs, IPlayerEvent, IRadioItemE /// /// Initializes a new instance of the class. /// - /// The player who is toggling a radio. + /// The player who is toggling a radio. /// The radio item. /// New state of the radio being turned off or on. - public PlayerTogglingRadioEventArgs(ReferenceHub player, BaseRadioItem radio, bool newState) + public PlayerTogglingRadioEventArgs(ReferenceHub hub, BaseRadioItem radio, bool newState) { IsAllowed = true; - Player = Player.Get(player); + Player = Player.Get(hub); RadioItem = RadioItem.Get(radio); NewState = newState; } diff --git a/LabApi/Events/Arguments/PlayerEvents/PlayerTogglingWeaponFlashlightEventArgs.cs b/LabApi/Events/Arguments/PlayerEvents/PlayerTogglingWeaponFlashlightEventArgs.cs index 7db324ab..35fb4b22 100644 --- a/LabApi/Events/Arguments/PlayerEvents/PlayerTogglingWeaponFlashlightEventArgs.cs +++ b/LabApi/Events/Arguments/PlayerEvents/PlayerTogglingWeaponFlashlightEventArgs.cs @@ -13,13 +13,13 @@ public class PlayerTogglingWeaponFlashlightEventArgs : EventArgs, IPlayerEvent, /// /// Initializes a new instance of the class. /// - /// The player who is toggling the flashlight. + /// The player who is toggling the flashlight. /// The flashlight item. /// The new state of the flashlight. - public PlayerTogglingWeaponFlashlightEventArgs(ReferenceHub player, Firearm item, bool newState) + public PlayerTogglingWeaponFlashlightEventArgs(ReferenceHub hub, Firearm item, bool newState) { IsAllowed = true; - Player = Player.Get(player); + Player = Player.Get(hub); FirearmItem = FirearmItem.Get(item); NewState = newState; } diff --git a/LabApi/Events/Arguments/PlayerEvents/PlayerTriggeredTeslaEventArgs.cs b/LabApi/Events/Arguments/PlayerEvents/PlayerTriggeredTeslaEventArgs.cs index b007c9ff..05889a0f 100644 --- a/LabApi/Events/Arguments/PlayerEvents/PlayerTriggeredTeslaEventArgs.cs +++ b/LabApi/Events/Arguments/PlayerEvents/PlayerTriggeredTeslaEventArgs.cs @@ -1,6 +1,6 @@ -using System; -using LabApi.Events.Arguments.Interfaces; +using LabApi.Events.Arguments.Interfaces; using LabApi.Features.Wrappers; +using System; namespace LabApi.Events.Arguments.PlayerEvents; diff --git a/LabApi/Events/Arguments/PlayerEvents/PlayerTriggeringTeslaEventArgs.cs b/LabApi/Events/Arguments/PlayerEvents/PlayerTriggeringTeslaEventArgs.cs index 9c4ccf42..9faa14b0 100644 --- a/LabApi/Events/Arguments/PlayerEvents/PlayerTriggeringTeslaEventArgs.cs +++ b/LabApi/Events/Arguments/PlayerEvents/PlayerTriggeringTeslaEventArgs.cs @@ -1,6 +1,6 @@ -using System; -using LabApi.Events.Arguments.Interfaces; +using LabApi.Events.Arguments.Interfaces; using LabApi.Features.Wrappers; +using System; namespace LabApi.Events.Arguments.PlayerEvents; diff --git a/LabApi/Events/Arguments/PlayerEvents/PlayerUncuffedEventArgs.cs b/LabApi/Events/Arguments/PlayerEvents/PlayerUncuffedEventArgs.cs index ad0c759d..eb8c6f62 100644 --- a/LabApi/Events/Arguments/PlayerEvents/PlayerUncuffedEventArgs.cs +++ b/LabApi/Events/Arguments/PlayerEvents/PlayerUncuffedEventArgs.cs @@ -12,12 +12,12 @@ public class PlayerUncuffedEventArgs : EventArgs, IPlayerEvent, ITargetEvent /// /// Initializes a new instance of the class. /// - /// The player who uncuffed target player. + /// The player who uncuffed target player. /// The player who was uncuffed. /// Whenever the player can undetain as SCP player. - public PlayerUncuffedEventArgs(ReferenceHub player, ReferenceHub target, bool canUnDetainAsScp) + public PlayerUncuffedEventArgs(ReferenceHub hub, ReferenceHub target, bool canUnDetainAsScp) { - Player = Player.Get(player); + Player = Player.Get(hub); Target = Player.Get(target); CanUnDetainAsScp = canUnDetainAsScp; } diff --git a/LabApi/Events/Arguments/PlayerEvents/PlayerUncuffingEventArgs.cs b/LabApi/Events/Arguments/PlayerEvents/PlayerUncuffingEventArgs.cs index 478b2a38..88b9f29c 100644 --- a/LabApi/Events/Arguments/PlayerEvents/PlayerUncuffingEventArgs.cs +++ b/LabApi/Events/Arguments/PlayerEvents/PlayerUncuffingEventArgs.cs @@ -12,13 +12,13 @@ public class PlayerUncuffingEventArgs : EventArgs, IPlayerEvent, ITargetEvent, I /// /// Initializes a new instance of the class. /// - /// The player who is uncuffing another player. + /// The player who is uncuffing another player. /// The player who is being uncuffed. - /// Whenever the player can undetain as SCP player - public PlayerUncuffingEventArgs(ReferenceHub player, ReferenceHub target, bool canUnDetainAsScp) + /// Whenever the player can undetain as SCP player. + public PlayerUncuffingEventArgs(ReferenceHub hub, ReferenceHub target, bool canUnDetainAsScp) { IsAllowed = true; - Player = Player.Get(player); + Player = Player.Get(hub); Target = Player.Get(target); CanUnDetainAsScp = canUnDetainAsScp; } diff --git a/LabApi/Events/Arguments/PlayerEvents/PlayerUnloadedWeaponEventArgs.cs b/LabApi/Events/Arguments/PlayerEvents/PlayerUnloadedWeaponEventArgs.cs index 06fadf1d..894cdb89 100644 --- a/LabApi/Events/Arguments/PlayerEvents/PlayerUnloadedWeaponEventArgs.cs +++ b/LabApi/Events/Arguments/PlayerEvents/PlayerUnloadedWeaponEventArgs.cs @@ -13,11 +13,11 @@ public class PlayerUnloadedWeaponEventArgs : EventArgs, IPlayerEvent, IFirearmIt /// /// Initializes a new instance of the class. /// - /// The player who unloaded the weapon. + /// The player who unloaded the weapon. /// The weapon that was unloaded. - public PlayerUnloadedWeaponEventArgs(ReferenceHub player, Firearm weapon) + public PlayerUnloadedWeaponEventArgs(ReferenceHub hub, Firearm weapon) { - Player = Player.Get(player); + Player = Player.Get(hub); FirearmItem = FirearmItem.Get(weapon); } diff --git a/LabApi/Events/Arguments/PlayerEvents/PlayerUnloadingWeaponEventArgs.cs b/LabApi/Events/Arguments/PlayerEvents/PlayerUnloadingWeaponEventArgs.cs index 17c3a9df..aae73d46 100644 --- a/LabApi/Events/Arguments/PlayerEvents/PlayerUnloadingWeaponEventArgs.cs +++ b/LabApi/Events/Arguments/PlayerEvents/PlayerUnloadingWeaponEventArgs.cs @@ -13,12 +13,12 @@ public class PlayerUnloadingWeaponEventArgs : EventArgs, IPlayerEvent, IFirearmI /// /// Initializes a new instance of the class. /// - /// The player who is unloading a weapon. + /// The player who is unloading a weapon. /// The weapon that is being unloaded. - public PlayerUnloadingWeaponEventArgs(ReferenceHub player, Firearm weapon) + public PlayerUnloadingWeaponEventArgs(ReferenceHub hub, Firearm weapon) { IsAllowed = true; - Player = Player.Get(player); + Player = Player.Get(hub); FirearmItem = FirearmItem.Get(weapon); } diff --git a/LabApi/Events/Arguments/PlayerEvents/PlayerUnlockedGeneratorEventArgs.cs b/LabApi/Events/Arguments/PlayerEvents/PlayerUnlockedGeneratorEventArgs.cs index dfa00707..984b533d 100644 --- a/LabApi/Events/Arguments/PlayerEvents/PlayerUnlockedGeneratorEventArgs.cs +++ b/LabApi/Events/Arguments/PlayerEvents/PlayerUnlockedGeneratorEventArgs.cs @@ -13,11 +13,11 @@ public class PlayerUnlockedGeneratorEventArgs : EventArgs, IPlayerEvent, IGenera /// /// Initializes a new instance of the class. /// - /// The player who unlocked the generator. + /// The player who unlocked the generator. /// The generator that the player has unlocked. - public PlayerUnlockedGeneratorEventArgs(ReferenceHub player, Scp079Generator generator) + public PlayerUnlockedGeneratorEventArgs(ReferenceHub hub, Scp079Generator generator) { - Player = Player.Get(player); + Player = Player.Get(hub); Generator = Generator.Get(generator); } @@ -29,4 +29,3 @@ public PlayerUnlockedGeneratorEventArgs(ReferenceHub player, Scp079Generator gen /// public Generator Generator { get; } } - diff --git a/LabApi/Events/Arguments/PlayerEvents/PlayerUnlockedWarheadButtonEventArgs.cs b/LabApi/Events/Arguments/PlayerEvents/PlayerUnlockedWarheadButtonEventArgs.cs index 445d543e..75bdc67b 100644 --- a/LabApi/Events/Arguments/PlayerEvents/PlayerUnlockedWarheadButtonEventArgs.cs +++ b/LabApi/Events/Arguments/PlayerEvents/PlayerUnlockedWarheadButtonEventArgs.cs @@ -12,10 +12,10 @@ public class PlayerUnlockedWarheadButtonEventArgs : EventArgs, IPlayerEvent /// /// Initializes a new instance of the class. /// - /// The player who has unlocked the warhead button. - public PlayerUnlockedWarheadButtonEventArgs(ReferenceHub player) + /// The player who has unlocked the warhead button. + public PlayerUnlockedWarheadButtonEventArgs(ReferenceHub hub) { - Player = Player.Get(player); + Player = Player.Get(hub); } /// @@ -23,4 +23,3 @@ public PlayerUnlockedWarheadButtonEventArgs(ReferenceHub player) /// public Player Player { get; } } - diff --git a/LabApi/Events/Arguments/PlayerEvents/PlayerUnlockingGeneratorEventArgs.cs b/LabApi/Events/Arguments/PlayerEvents/PlayerUnlockingGeneratorEventArgs.cs index 9cb18a10..fdde7102 100644 --- a/LabApi/Events/Arguments/PlayerEvents/PlayerUnlockingGeneratorEventArgs.cs +++ b/LabApi/Events/Arguments/PlayerEvents/PlayerUnlockingGeneratorEventArgs.cs @@ -13,12 +13,12 @@ public class PlayerUnlockingGeneratorEventArgs : EventArgs, IPlayerEvent, IGener /// /// Initializes a new instance of the class. /// - /// The player who is unlocking the generator. + /// The player who is unlocking the generator. /// The generator that the player is unlocking. /// Whether the generator can be opened. - public PlayerUnlockingGeneratorEventArgs(ReferenceHub player, Scp079Generator generator, bool canOpen) + public PlayerUnlockingGeneratorEventArgs(ReferenceHub hub, Scp079Generator generator, bool canOpen) { - Player = Player.Get(player); + Player = Player.Get(hub); Generator = Generator.Get(generator); IsAllowed = true; CanOpen = canOpen; @@ -42,4 +42,3 @@ public PlayerUnlockingGeneratorEventArgs(ReferenceHub player, Scp079Generator ge /// public bool IsAllowed { get; set; } } - diff --git a/LabApi/Events/Arguments/PlayerEvents/PlayerUnlockingWarheadButtonEventArgs.cs b/LabApi/Events/Arguments/PlayerEvents/PlayerUnlockingWarheadButtonEventArgs.cs index 8e6a3980..f3bbfedf 100644 --- a/LabApi/Events/Arguments/PlayerEvents/PlayerUnlockingWarheadButtonEventArgs.cs +++ b/LabApi/Events/Arguments/PlayerEvents/PlayerUnlockingWarheadButtonEventArgs.cs @@ -12,10 +12,10 @@ public class PlayerUnlockingWarheadButtonEventArgs : EventArgs, IPlayerEvent, IC /// /// Initializes a new instance of the class. /// - /// The player who unlocking the warhead button. - public PlayerUnlockingWarheadButtonEventArgs(ReferenceHub player) + /// The player who unlocking the warhead button. + public PlayerUnlockingWarheadButtonEventArgs(ReferenceHub hub) { - Player = Player.Get(player); + Player = Player.Get(hub); IsAllowed = true; } diff --git a/LabApi/Events/Arguments/PlayerEvents/PlayerUnmutedEventArgs.cs b/LabApi/Events/Arguments/PlayerEvents/PlayerUnmutedEventArgs.cs index a6056c27..948931a0 100644 --- a/LabApi/Events/Arguments/PlayerEvents/PlayerUnmutedEventArgs.cs +++ b/LabApi/Events/Arguments/PlayerEvents/PlayerUnmutedEventArgs.cs @@ -12,12 +12,12 @@ public class PlayerUnmutedEventArgs : EventArgs, IPlayerEvent /// /// Initializes a new instance of the class. /// - /// The player who was unmuted. + /// The player who was unmuted. /// The player who issued the unmute. /// Whenever the unmute was for intercom. - public PlayerUnmutedEventArgs(ReferenceHub player, ReferenceHub issuer, bool isIntercom) + public PlayerUnmutedEventArgs(ReferenceHub hub, ReferenceHub issuer, bool isIntercom) { - Player = Player.Get(player); + Player = Player.Get(hub); Issuer = Player.Get(issuer); IsIntercom = isIntercom; } diff --git a/LabApi/Events/Arguments/PlayerEvents/PlayerUnmutingEventArgs.cs b/LabApi/Events/Arguments/PlayerEvents/PlayerUnmutingEventArgs.cs index f731e090..9b0d15e9 100644 --- a/LabApi/Events/Arguments/PlayerEvents/PlayerUnmutingEventArgs.cs +++ b/LabApi/Events/Arguments/PlayerEvents/PlayerUnmutingEventArgs.cs @@ -12,13 +12,13 @@ public class PlayerUnmutingEventArgs : EventArgs, IPlayerEvent, ICancellableEven /// /// Initializes a new instance of the class. /// - /// The player who is being unmuted. + /// The player who is being unmuted. /// The player who issued the unmute action. /// Whenever is unmute for intercom. - public PlayerUnmutingEventArgs(ReferenceHub player, ReferenceHub issuer, bool isIntercom) + public PlayerUnmutingEventArgs(ReferenceHub hub, ReferenceHub issuer, bool isIntercom) { IsAllowed = true; - Player = Player.Get(player); + Player = Player.Get(hub); Issuer = Player.Get(issuer); IsIntercom = isIntercom; } diff --git a/LabApi/Events/Arguments/PlayerEvents/PlayerUsedIntercomEventArgs.cs b/LabApi/Events/Arguments/PlayerEvents/PlayerUsedIntercomEventArgs.cs index e037a2de..cec2c8be 100644 --- a/LabApi/Events/Arguments/PlayerEvents/PlayerUsedIntercomEventArgs.cs +++ b/LabApi/Events/Arguments/PlayerEvents/PlayerUsedIntercomEventArgs.cs @@ -13,11 +13,11 @@ public class PlayerUsedIntercomEventArgs : EventArgs, IPlayerEvent /// /// Initializes a new instance of the class. /// - /// The player who used the intercom. + /// The player who used the intercom. /// State of the intercom. - public PlayerUsedIntercomEventArgs(ReferenceHub? player, IntercomState state) + public PlayerUsedIntercomEventArgs(ReferenceHub? hub, IntercomState state) { - Player = Player.Get(player); + Player = Player.Get(hub); State = state; } diff --git a/LabApi/Events/Arguments/PlayerEvents/PlayerUsedItemEventArgs.cs b/LabApi/Events/Arguments/PlayerEvents/PlayerUsedItemEventArgs.cs index 63766d64..885cc193 100644 --- a/LabApi/Events/Arguments/PlayerEvents/PlayerUsedItemEventArgs.cs +++ b/LabApi/Events/Arguments/PlayerEvents/PlayerUsedItemEventArgs.cs @@ -13,11 +13,11 @@ public class PlayerUsedItemEventArgs : EventArgs, IPlayerEvent, IUsableItemEvent /// /// Initializes a new instance of the class. /// - /// The player who used the item. + /// The player who used the item. /// Item that was used. - public PlayerUsedItemEventArgs(ReferenceHub player, BaseUsableItem item) + public PlayerUsedItemEventArgs(ReferenceHub hub, BaseUsableItem item) { - Player = Player.Get(player); + Player = Player.Get(hub); UsableItem = UsableItem.Get(item); } diff --git a/LabApi/Events/Arguments/PlayerEvents/PlayerUsedRadioEventArgs.cs b/LabApi/Events/Arguments/PlayerEvents/PlayerUsedRadioEventArgs.cs index 2d7ab251..b7d2a960 100644 --- a/LabApi/Events/Arguments/PlayerEvents/PlayerUsedRadioEventArgs.cs +++ b/LabApi/Events/Arguments/PlayerEvents/PlayerUsedRadioEventArgs.cs @@ -13,12 +13,12 @@ public class PlayerUsedRadioEventArgs : EventArgs, IPlayerEvent, IRadioItemEvent /// /// Initializes a new instance of the class. /// - /// Player that used the radio. + /// Player that used the radio. /// Radio that was being used. /// Drain amount of the battery per second. - public PlayerUsedRadioEventArgs(ReferenceHub player, BaseRadioItem radio, float drain) + public PlayerUsedRadioEventArgs(ReferenceHub hub, BaseRadioItem radio, float drain) { - Player = Player.Get(player); + Player = Player.Get(hub); RadioItem = RadioItem.Get(radio); Drain = drain; } diff --git a/LabApi/Events/Arguments/PlayerEvents/PlayerUsingIntercomEventArgs.cs b/LabApi/Events/Arguments/PlayerEvents/PlayerUsingIntercomEventArgs.cs index ec7f93bb..4bc1974d 100644 --- a/LabApi/Events/Arguments/PlayerEvents/PlayerUsingIntercomEventArgs.cs +++ b/LabApi/Events/Arguments/PlayerEvents/PlayerUsingIntercomEventArgs.cs @@ -13,13 +13,13 @@ public class PlayerUsingIntercomEventArgs : EventArgs, IPlayerEvent, ICancellabl /// /// Initializes a new instance of the class. /// - /// The player that is using the intercom. + /// The player that is using the intercom. /// State of the intercom. - //TODO: Add intercom class and ref it docs - public PlayerUsingIntercomEventArgs(ReferenceHub player, IntercomState state) + // TODO: Add intercom class and ref it docs + public PlayerUsingIntercomEventArgs(ReferenceHub hub, IntercomState state) { IsAllowed = true; - Player = Player.Get(player); + Player = Player.Get(hub); State = state; } diff --git a/LabApi/Events/Arguments/PlayerEvents/PlayerUsingItemEventArgs.cs b/LabApi/Events/Arguments/PlayerEvents/PlayerUsingItemEventArgs.cs index 48158bdf..9e08bb98 100644 --- a/LabApi/Events/Arguments/PlayerEvents/PlayerUsingItemEventArgs.cs +++ b/LabApi/Events/Arguments/PlayerEvents/PlayerUsingItemEventArgs.cs @@ -13,12 +13,12 @@ public class PlayerUsingItemEventArgs : EventArgs, IPlayerEvent, IUsableItemEven /// /// Initializes a new instance of the class. /// - /// The player using the item. + /// The player using the item. /// The item that is being used. - public PlayerUsingItemEventArgs(ReferenceHub player, BaseUsableItem item) + public PlayerUsingItemEventArgs(ReferenceHub hub, BaseUsableItem item) { IsAllowed = true; - Player = Player.Get(player); + Player = Player.Get(hub); UsableItem = UsableItem.Get(item); } diff --git a/LabApi/Events/Arguments/PlayerEvents/PlayerUsingRadioEventArgs.cs b/LabApi/Events/Arguments/PlayerEvents/PlayerUsingRadioEventArgs.cs index af5787ac..1e5abf67 100644 --- a/LabApi/Events/Arguments/PlayerEvents/PlayerUsingRadioEventArgs.cs +++ b/LabApi/Events/Arguments/PlayerEvents/PlayerUsingRadioEventArgs.cs @@ -13,13 +13,13 @@ public class PlayerUsingRadioEventArgs : EventArgs, IPlayerEvent, IRadioItemEven /// /// Initializes a new instance of the class. /// - /// The player who is using the radio. + /// The player who is using the radio. /// Radio item that is being used. /// Battery drain amount per second. - public PlayerUsingRadioEventArgs(ReferenceHub player, BaseRadioItem radio, float drain) + public PlayerUsingRadioEventArgs(ReferenceHub hub, BaseRadioItem radio, float drain) { IsAllowed = true; - Player = Player.Get(player); + Player = Player.Get(hub); RadioItem = RadioItem.Get(radio); Drain = drain; } diff --git a/LabApi/Events/Arguments/PlayerEvents/PlayerZoneChangedEventArgs.cs b/LabApi/Events/Arguments/PlayerEvents/PlayerZoneChangedEventArgs.cs new file mode 100644 index 00000000..6fc7fc2b --- /dev/null +++ b/LabApi/Events/Arguments/PlayerEvents/PlayerZoneChangedEventArgs.cs @@ -0,0 +1,40 @@ +using LabApi.Events.Arguments.Interfaces; +using LabApi.Features.Wrappers; +using MapGeneration; +using System; + +namespace LabApi.Events.Arguments.PlayerEvents; + +/// +/// Represents the arguments for the event. +/// +public class PlayerZoneChangedEventArgs : EventArgs, IPlayerEvent +{ + /// + /// Initializes a new instance of the class. + /// + /// The player whose zone changed. + /// The old zone. + /// The new zone. + public PlayerZoneChangedEventArgs(ReferenceHub player, FacilityZone oldZone, FacilityZone newZone) + { + Player = Player.Get(player); + OldZone = oldZone; + NewZone = newZone; + } + + /// + /// Gets the player whose last known room changed. + /// + public Player Player { get; } + + /// + /// Gets the old zone. May be if the player just spawned, went through void and such. + /// + public FacilityZone OldZone { get; } + + /// + /// Gets the new zone. May be if the player went into void, died and such. + /// + public FacilityZone NewZone { get; } +} diff --git a/LabApi/Events/Arguments/Scp0492Events/Scp0492ConsumedCorpseEventArgs.cs b/LabApi/Events/Arguments/Scp0492Events/Scp0492ConsumedCorpseEventArgs.cs index cbb3b2ae..62019aec 100644 --- a/LabApi/Events/Arguments/Scp0492Events/Scp0492ConsumedCorpseEventArgs.cs +++ b/LabApi/Events/Arguments/Scp0492Events/Scp0492ConsumedCorpseEventArgs.cs @@ -1,7 +1,7 @@ -using System; -using LabApi.Events.Arguments.Interfaces; +using LabApi.Events.Arguments.Interfaces; using LabApi.Features.Wrappers; using PlayerRoles.Ragdolls; +using System; namespace LabApi.Events.Arguments.Scp0492Events; diff --git a/LabApi/Events/Arguments/Scp0492Events/Scp0492ConsumingCorpseEventArgs.cs b/LabApi/Events/Arguments/Scp0492Events/Scp0492ConsumingCorpseEventArgs.cs index fd87c9f9..ce42bd82 100644 --- a/LabApi/Events/Arguments/Scp0492Events/Scp0492ConsumingCorpseEventArgs.cs +++ b/LabApi/Events/Arguments/Scp0492Events/Scp0492ConsumingCorpseEventArgs.cs @@ -1,7 +1,7 @@ -using System; -using LabApi.Events.Arguments.Interfaces; +using LabApi.Events.Arguments.Interfaces; using LabApi.Features.Wrappers; using PlayerRoles.Ragdolls; +using System; namespace LabApi.Events.Arguments.Scp0492Events; diff --git a/LabApi/Events/Arguments/Scp0492Events/Scp0492StartedConsumingCorpseEventArgs.cs b/LabApi/Events/Arguments/Scp0492Events/Scp0492StartedConsumingCorpseEventArgs.cs index 09b4374d..640188ae 100644 --- a/LabApi/Events/Arguments/Scp0492Events/Scp0492StartedConsumingCorpseEventArgs.cs +++ b/LabApi/Events/Arguments/Scp0492Events/Scp0492StartedConsumingCorpseEventArgs.cs @@ -1,7 +1,7 @@ -using System; -using LabApi.Events.Arguments.Interfaces; +using LabApi.Events.Arguments.Interfaces; using LabApi.Features.Wrappers; using PlayerRoles.Ragdolls; +using System; namespace LabApi.Events.Arguments.Scp0492Events; diff --git a/LabApi/Events/Arguments/Scp0492Events/Scp0492StartingConsumingCorpseEventArgs.cs b/LabApi/Events/Arguments/Scp0492Events/Scp0492StartingConsumingCorpseEventArgs.cs index b696c4a2..fa3b9d47 100644 --- a/LabApi/Events/Arguments/Scp0492Events/Scp0492StartingConsumingCorpseEventArgs.cs +++ b/LabApi/Events/Arguments/Scp0492Events/Scp0492StartingConsumingCorpseEventArgs.cs @@ -1,8 +1,8 @@ -using System; -using LabApi.Events.Arguments.Interfaces; +using LabApi.Events.Arguments.Interfaces; using LabApi.Features.Wrappers; using PlayerRoles.PlayableScps.Scp049.Zombies; using PlayerRoles.Ragdolls; +using System; namespace LabApi.Events.Arguments.Scp0492Events; diff --git a/LabApi/Events/Arguments/Scp049Events/Scp049AttackedEventArgs.cs b/LabApi/Events/Arguments/Scp049Events/Scp049AttackedEventArgs.cs new file mode 100644 index 00000000..0a227784 --- /dev/null +++ b/LabApi/Events/Arguments/Scp049Events/Scp049AttackedEventArgs.cs @@ -0,0 +1,46 @@ +using LabApi.Events.Arguments.Interfaces; +using LabApi.Features.Wrappers; +using System; + +namespace LabApi.Events.Arguments.Scp049Events; + +/// +/// Represents the arguments for the event. +/// +public class Scp049AttackedEventArgs : EventArgs, IPlayerEvent, ITargetEvent +{ + /// + /// Initializes a new instance of the class. + /// + /// The SCP-049 player instance. + /// The player that SCP-049 has attacked. + /// The attack was an instant kill. + /// The was a sense target. + public Scp049AttackedEventArgs(ReferenceHub hub, ReferenceHub target, bool instantKill, bool isSenseTarget) + { + Player = Player.Get(hub); + Target = Player.Get(target); + InstantKill = instantKill; + IsSenseTarget = isSenseTarget; + } + + /// + /// The SCP-049 player instance. + /// + public Player Player { get; } + + /// + /// The player that SCP-049 has attacked. + /// + public Player Target { get; } + + /// + /// Gets whether the attack was an instant kill. + /// + public bool InstantKill { get; } + + /// + /// Gets whether the is a sense target. + /// + public bool IsSenseTarget { get; } +} \ No newline at end of file diff --git a/LabApi/Events/Arguments/Scp049Events/Scp049AttackingEventArgs.cs b/LabApi/Events/Arguments/Scp049Events/Scp049AttackingEventArgs.cs new file mode 100644 index 00000000..8568470b --- /dev/null +++ b/LabApi/Events/Arguments/Scp049Events/Scp049AttackingEventArgs.cs @@ -0,0 +1,58 @@ +using LabApi.Events.Arguments.Interfaces; +using LabApi.Features.Wrappers; +using System; + +namespace LabApi.Events.Arguments.Scp049Events; + +/// +/// Represents the arguments for the event. +/// +public class Scp049AttackingEventArgs : EventArgs, IPlayerEvent, ITargetEvent, ICancellableEvent +{ + /// + /// Initializes a new instance of the class. + /// + /// The SCP-049 player instance. + /// The player that SCP-049 is attacking. + /// The attack is an instant kill. + /// The is a sense target. + /// The attack cooldown. + public Scp049AttackingEventArgs(ReferenceHub hub, ReferenceHub target, bool instantKill, bool isSenseTarget, float cooldownTime) + { + Player = Player.Get(hub); + Target = Player.Get(target); + InstantKill = instantKill; + IsSenseTarget = isSenseTarget; + CooldownTime = cooldownTime; + + IsAllowed = true; + } + + /// + /// The SCP-049 player instance. + /// + public Player Player { get; } + + /// + /// The player that SCP-049 is attacking. + /// + public Player Target { get; } + + /// + /// Gets or sets whether the attack is an instant kill. + /// + public bool InstantKill { get; set; } + + /// + /// Gets or sets whether the is a sense target. + /// + public bool IsSenseTarget { get; set; } + + /// + /// Gets or sets the cooldown for the attack ability. + /// + public float CooldownTime { get; set; } + + /// + public bool IsAllowed { get; set; } +} \ No newline at end of file diff --git a/LabApi/Events/Arguments/Scp049Events/Scp049ResurrectedBodyEventArgs.cs b/LabApi/Events/Arguments/Scp049Events/Scp049ResurrectedBodyEventArgs.cs index 7eba4f2d..2a4359d1 100644 --- a/LabApi/Events/Arguments/Scp049Events/Scp049ResurrectedBodyEventArgs.cs +++ b/LabApi/Events/Arguments/Scp049Events/Scp049ResurrectedBodyEventArgs.cs @@ -13,11 +13,11 @@ public class Scp049ResurrectedBodyEventArgs : EventArgs, IPlayerEvent, ITargetEv /// Initializes a new instance of the class. /// /// The player that SCP-049 has resurrected. - /// The SCP-049 player instance. - public Scp049ResurrectedBodyEventArgs(ReferenceHub target, ReferenceHub player) + /// The SCP-049 player instance. + public Scp049ResurrectedBodyEventArgs(ReferenceHub target, ReferenceHub hub) { Target = Player.Get(target); - Player = Player.Get(player); + Player = Player.Get(hub); } /// diff --git a/LabApi/Events/Arguments/Scp049Events/Scp049ResurrectingBodyEventArgs.cs b/LabApi/Events/Arguments/Scp049Events/Scp049ResurrectingBodyEventArgs.cs index dac207f0..0e54e263 100644 --- a/LabApi/Events/Arguments/Scp049Events/Scp049ResurrectingBodyEventArgs.cs +++ b/LabApi/Events/Arguments/Scp049Events/Scp049ResurrectingBodyEventArgs.cs @@ -14,12 +14,12 @@ public class Scp049ResurrectingBodyEventArgs : EventArgs, ICancellableEvent, IPl /// /// The ragdoll that SCP-049 is resurrecting. /// The player that SCP-049 is resurrecting. - /// The SCP-049 player instance. - public Scp049ResurrectingBodyEventArgs(Ragdoll ragdoll, ReferenceHub target, ReferenceHub player) + /// The SCP-049 player instance. + public Scp049ResurrectingBodyEventArgs(Ragdoll ragdoll, ReferenceHub target, ReferenceHub hub) { Ragdoll = ragdoll; Target = Player.Get(target); - Player = Player.Get(player); + Player = Player.Get(hub); IsAllowed = true; } diff --git a/LabApi/Events/Arguments/Scp049Events/Scp049SenseKilledTargetEventArgs.cs b/LabApi/Events/Arguments/Scp049Events/Scp049SenseKilledTargetEventArgs.cs new file mode 100644 index 00000000..96e557ad --- /dev/null +++ b/LabApi/Events/Arguments/Scp049Events/Scp049SenseKilledTargetEventArgs.cs @@ -0,0 +1,32 @@ +using LabApi.Events.Arguments.Interfaces; +using LabApi.Features.Wrappers; +using System; + +namespace LabApi.Events.Arguments.Scp049Events; + +/// +/// Represents the arguments for the event. +/// +public class Scp049SenseKilledTargetEventArgs : EventArgs, IPlayerEvent, ITargetEvent +{ + /// + /// Initializes a new instance of the class. + /// + /// The SCP-049 player instance. + /// The player that SCP-049 killed. + public Scp049SenseKilledTargetEventArgs(ReferenceHub hub, ReferenceHub target) + { + Player = Player.Get(hub); + Target = Player.Get(target); + } + + /// + /// The SCP-049 player instance. + /// + public Player Player { get; } + + /// + /// The player that SCP-049 has killed. + /// + public Player Target { get; } +} \ No newline at end of file diff --git a/LabApi/Events/Arguments/Scp049Events/Scp049SenseLostTargetEventArgs.cs b/LabApi/Events/Arguments/Scp049Events/Scp049SenseLostTargetEventArgs.cs new file mode 100644 index 00000000..89b564e3 --- /dev/null +++ b/LabApi/Events/Arguments/Scp049Events/Scp049SenseLostTargetEventArgs.cs @@ -0,0 +1,32 @@ +using LabApi.Events.Arguments.Interfaces; +using LabApi.Features.Wrappers; +using System; + +namespace LabApi.Events.Arguments.Scp049Events; + +/// +/// Represents the arguments for the event. +/// +public class Scp049SenseLostTargetEventArgs : EventArgs, IPlayerEvent, ITargetEvent +{ + /// + /// Initializes a new instance of the class. + /// + /// The SCP-049 player instance. + /// The player that SCP-049 has targeted. + public Scp049SenseLostTargetEventArgs(ReferenceHub hub, ReferenceHub target) + { + Player = Player.Get(hub); + Target = Player.Get(target); + } + + /// + /// The SCP-049 player instance. + /// + public Player Player { get; } + + /// + /// The player that SCP-049 has targeted. + /// + public Player? Target { get; } +} \ No newline at end of file diff --git a/LabApi/Events/Arguments/Scp049Events/Scp049StartingResurrectionEventArgs.cs b/LabApi/Events/Arguments/Scp049Events/Scp049StartingResurrectionEventArgs.cs index a8f04cf8..8775f681 100644 --- a/LabApi/Events/Arguments/Scp049Events/Scp049StartingResurrectionEventArgs.cs +++ b/LabApi/Events/Arguments/Scp049Events/Scp049StartingResurrectionEventArgs.cs @@ -16,13 +16,13 @@ public class Scp049StartingResurrectionEventArgs : EventArgs, ICancellableEvent, /// Whether SCP-049 can resurrect the ragdoll. /// The ragdoll that SCP-049 is resurrecting. /// The owner of the ragdoll that SCP-049 is resurrecting. - /// The SCP-049 player instance. - public Scp049StartingResurrectionEventArgs(bool canResurrect, BasicRagdoll ragdoll, ReferenceHub? target, ReferenceHub player) + /// The SCP-049 player instance. + public Scp049StartingResurrectionEventArgs(bool canResurrect, BasicRagdoll ragdoll, ReferenceHub? target, ReferenceHub hub) { CanResurrect = canResurrect; Ragdoll = Ragdoll.Get(ragdoll); Target = Player.Get(target); - Player = Player.Get(player); + Player = Player.Get(hub); IsAllowed = true; } diff --git a/LabApi/Events/Arguments/Scp049Events/Scp049UsedDoctorsCallEventArgs.cs b/LabApi/Events/Arguments/Scp049Events/Scp049UsedDoctorsCallEventArgs.cs index d358388a..78ca5252 100644 --- a/LabApi/Events/Arguments/Scp049Events/Scp049UsedDoctorsCallEventArgs.cs +++ b/LabApi/Events/Arguments/Scp049Events/Scp049UsedDoctorsCallEventArgs.cs @@ -12,10 +12,10 @@ public class Scp049UsedDoctorsCallEventArgs : EventArgs, IPlayerEvent /// /// Initializes a new instance of the class. /// - /// The SCP-049 player instance. - public Scp049UsedDoctorsCallEventArgs(ReferenceHub player) + /// The SCP-049 player instance. + public Scp049UsedDoctorsCallEventArgs(ReferenceHub hub) { - Player = Player.Get(player); + Player = Player.Get(hub); } /// diff --git a/LabApi/Events/Arguments/Scp049Events/Scp049UsedSenseEventArgs.cs b/LabApi/Events/Arguments/Scp049Events/Scp049UsedSenseEventArgs.cs index 14c13d37..2d116944 100644 --- a/LabApi/Events/Arguments/Scp049Events/Scp049UsedSenseEventArgs.cs +++ b/LabApi/Events/Arguments/Scp049Events/Scp049UsedSenseEventArgs.cs @@ -12,11 +12,11 @@ public class Scp049UsedSenseEventArgs : EventArgs, IPlayerEvent, ITargetEvent /// /// Initializes a new instance of the class. /// - /// The SCP-049 player instance. + /// The SCP-049 player instance. /// The player that SCP-049 has used sense on. - public Scp049UsedSenseEventArgs(ReferenceHub player, ReferenceHub target) + public Scp049UsedSenseEventArgs(ReferenceHub hub, ReferenceHub target) { - Player = Player.Get(player); + Player = Player.Get(hub); Target = Player.Get(target); } diff --git a/LabApi/Events/Arguments/Scp049Events/Scp049UsingDoctorsCallEventArgs.cs b/LabApi/Events/Arguments/Scp049Events/Scp049UsingDoctorsCallEventArgs.cs index a737c994..c3fbcb5a 100644 --- a/LabApi/Events/Arguments/Scp049Events/Scp049UsingDoctorsCallEventArgs.cs +++ b/LabApi/Events/Arguments/Scp049Events/Scp049UsingDoctorsCallEventArgs.cs @@ -12,10 +12,10 @@ public class Scp049UsingDoctorsCallEventArgs : EventArgs, IPlayerEvent, ICancell /// /// Initializes a new instance of the class. /// - /// The SCP-049 player instance. - public Scp049UsingDoctorsCallEventArgs(ReferenceHub player) + /// The SCP-049 player instance. + public Scp049UsingDoctorsCallEventArgs(ReferenceHub hub) { - Player = Player.Get(player); + Player = Player.Get(hub); IsAllowed = true; } diff --git a/LabApi/Events/Arguments/Scp049Events/Scp049UsingSenseEventArgs.cs b/LabApi/Events/Arguments/Scp049Events/Scp049UsingSenseEventArgs.cs index 57bb77cc..89f0b8db 100644 --- a/LabApi/Events/Arguments/Scp049Events/Scp049UsingSenseEventArgs.cs +++ b/LabApi/Events/Arguments/Scp049Events/Scp049UsingSenseEventArgs.cs @@ -12,11 +12,11 @@ public class Scp049UsingSenseEventArgs : EventArgs, IPlayerEvent, ITargetEvent, /// /// Initializes a new instance of the class. /// - /// The SCP-049 player instance. + /// The SCP-049 player instance. /// The player that SCP-049 is using sense on. - public Scp049UsingSenseEventArgs(ReferenceHub player, ReferenceHub target) + public Scp049UsingSenseEventArgs(ReferenceHub hub, ReferenceHub target) { - Player = Player.Get(player); + Player = Player.Get(hub); Target = Player.Get(target); IsAllowed = true; } diff --git a/LabApi/Events/Arguments/Scp079Events/Scp079BlackedOutRoomEventArgs.cs b/LabApi/Events/Arguments/Scp079Events/Scp079BlackedOutRoomEventArgs.cs index 1bc79797..7c8616a8 100644 --- a/LabApi/Events/Arguments/Scp079Events/Scp079BlackedOutRoomEventArgs.cs +++ b/LabApi/Events/Arguments/Scp079Events/Scp079BlackedOutRoomEventArgs.cs @@ -1,7 +1,7 @@ using LabApi.Events.Arguments.Interfaces; using LabApi.Features.Wrappers; -using System; using MapGeneration; +using System; namespace LabApi.Events.Arguments.Scp079Events; @@ -13,11 +13,11 @@ public class Scp079BlackedOutRoomEventArgs : EventArgs, IPlayerEvent, IRoomEvent /// /// Initializes a new instance of the class. /// - /// The SCP-079 player instance. + /// The SCP-079 player instance. /// The affected room instance. - public Scp079BlackedOutRoomEventArgs(ReferenceHub player, RoomIdentifier room) + public Scp079BlackedOutRoomEventArgs(ReferenceHub hub, RoomIdentifier room) { - Player = Player.Get(player); + Player = Player.Get(hub); Room = Room.Get(room); } diff --git a/LabApi/Events/Arguments/Scp079Events/Scp079BlackedOutZoneEventArgs.cs b/LabApi/Events/Arguments/Scp079Events/Scp079BlackedOutZoneEventArgs.cs index 112c7fe6..b2e17fa6 100644 --- a/LabApi/Events/Arguments/Scp079Events/Scp079BlackedOutZoneEventArgs.cs +++ b/LabApi/Events/Arguments/Scp079Events/Scp079BlackedOutZoneEventArgs.cs @@ -13,11 +13,11 @@ public class Scp079BlackedOutZoneEventArgs : EventArgs, IPlayerEvent /// /// Initializes a new instance of the class. /// - /// The SCP-079 player instance. + /// The SCP-079 player instance. /// The affected zone instance. - public Scp079BlackedOutZoneEventArgs(ReferenceHub player, FacilityZone zone) + public Scp079BlackedOutZoneEventArgs(ReferenceHub hub, FacilityZone zone) { - Player = Player.Get(player); + Player = Player.Get(hub); Zone = zone; } diff --git a/LabApi/Events/Arguments/Scp079Events/Scp079BlackingOutRoomEventsArgs.cs b/LabApi/Events/Arguments/Scp079Events/Scp079BlackingOutRoomEventsArgs.cs index c65a59cd..9d409f33 100644 --- a/LabApi/Events/Arguments/Scp079Events/Scp079BlackingOutRoomEventsArgs.cs +++ b/LabApi/Events/Arguments/Scp079Events/Scp079BlackingOutRoomEventsArgs.cs @@ -1,7 +1,7 @@ using LabApi.Events.Arguments.Interfaces; using LabApi.Features.Wrappers; -using System; using MapGeneration; +using System; namespace LabApi.Events.Arguments.Scp079Events; @@ -13,11 +13,11 @@ public class Scp079BlackingOutRoomEventsArgs : EventArgs, IPlayerEvent, IRoomEve /// /// Initializes a new instance of the class. /// - /// The SCP-079 player instance. + /// The SCP-079 player instance. /// The affected room instance. - public Scp079BlackingOutRoomEventsArgs(ReferenceHub player, RoomIdentifier room) + public Scp079BlackingOutRoomEventsArgs(ReferenceHub hub, RoomIdentifier room) { - Player = Player.Get(player); + Player = Player.Get(hub); Room = Room.Get(room); IsAllowed = true; } diff --git a/LabApi/Events/Arguments/Scp079Events/Scp079BlackingOutZoneEventArgs.cs b/LabApi/Events/Arguments/Scp079Events/Scp079BlackingOutZoneEventArgs.cs index 2c67fd05..aad04ab5 100644 --- a/LabApi/Events/Arguments/Scp079Events/Scp079BlackingOutZoneEventArgs.cs +++ b/LabApi/Events/Arguments/Scp079Events/Scp079BlackingOutZoneEventArgs.cs @@ -13,11 +13,11 @@ public class Scp079BlackingOutZoneEventArgs : EventArgs, IPlayerEvent, ICancella /// /// Initializes a new instance of the class. /// - /// The SCP-079 player instance. + /// The SCP-079 player instance. /// The affected zone instance. - public Scp079BlackingOutZoneEventArgs(ReferenceHub player, FacilityZone zone) + public Scp079BlackingOutZoneEventArgs(ReferenceHub hub, FacilityZone zone) { - Player = Player.Get(player); + Player = Player.Get(hub); Zone = zone; IsAllowed = true; } diff --git a/LabApi/Events/Arguments/Scp079Events/Scp079CancelledRoomLockdownEventArgs.cs b/LabApi/Events/Arguments/Scp079Events/Scp079CancelledRoomLockdownEventArgs.cs index 5a0399e9..9ea59d04 100644 --- a/LabApi/Events/Arguments/Scp079Events/Scp079CancelledRoomLockdownEventArgs.cs +++ b/LabApi/Events/Arguments/Scp079Events/Scp079CancelledRoomLockdownEventArgs.cs @@ -1,7 +1,7 @@ using LabApi.Events.Arguments.Interfaces; using LabApi.Features.Wrappers; -using System; using MapGeneration; +using System; namespace LabApi.Events.Arguments.Scp079Events; @@ -13,11 +13,11 @@ public class Scp079CancelledRoomLockdownEventArgs : EventArgs, IPlayerEvent, IRo /// /// Initializes a new instance of the class. /// - /// The SCP-079 player instance. + /// The SCP-079 player instance. /// The affected room instance. - public Scp079CancelledRoomLockdownEventArgs(ReferenceHub player, RoomIdentifier room) + public Scp079CancelledRoomLockdownEventArgs(ReferenceHub hub, RoomIdentifier room) { - Player = Player.Get(player); + Player = Player.Get(hub); Room = Room.Get(room); } diff --git a/LabApi/Events/Arguments/Scp079Events/Scp079CancellingRoomLockdownEventArgs.cs b/LabApi/Events/Arguments/Scp079Events/Scp079CancellingRoomLockdownEventArgs.cs index 756326e0..173bbab0 100644 --- a/LabApi/Events/Arguments/Scp079Events/Scp079CancellingRoomLockdownEventArgs.cs +++ b/LabApi/Events/Arguments/Scp079Events/Scp079CancellingRoomLockdownEventArgs.cs @@ -1,7 +1,7 @@ using LabApi.Events.Arguments.Interfaces; using LabApi.Features.Wrappers; -using System; using MapGeneration; +using System; namespace LabApi.Events.Arguments.Scp079Events; @@ -13,11 +13,11 @@ public class Scp079CancellingRoomLockdownEventArgs : EventArgs, IPlayerEvent, IR /// /// Initializes a new instance of the class. /// - /// The SCP-079 player instance. + /// The SCP-079 player instance. /// The affected room instance. - public Scp079CancellingRoomLockdownEventArgs(ReferenceHub player, RoomIdentifier room) + public Scp079CancellingRoomLockdownEventArgs(ReferenceHub hub, RoomIdentifier room) { - Player = Player.Get(player); + Player = Player.Get(hub); Room = Room.Get(room); IsAllowed = true; } diff --git a/LabApi/Events/Arguments/Scp079Events/Scp079ChangedCameraEventArgs.cs b/LabApi/Events/Arguments/Scp079Events/Scp079ChangedCameraEventArgs.cs index 743ccef1..856dacbd 100644 --- a/LabApi/Events/Arguments/Scp079Events/Scp079ChangedCameraEventArgs.cs +++ b/LabApi/Events/Arguments/Scp079Events/Scp079ChangedCameraEventArgs.cs @@ -13,11 +13,11 @@ public class Scp079ChangedCameraEventArgs : EventArgs, IPlayerEvent, ICameraEven /// /// Initializes a new instance of the class. /// - /// The SCP-079 player instance. + /// The SCP-079 player instance. /// The affected camera instance. - public Scp079ChangedCameraEventArgs(ReferenceHub player, Scp079Camera camera) + public Scp079ChangedCameraEventArgs(ReferenceHub hub, Scp079Camera camera) { - Player = Player.Get(player); + Player = Player.Get(hub); Camera = Camera.Get(camera); } diff --git a/LabApi/Events/Arguments/Scp079Events/Scp079ChangingCameraEventArgs.cs b/LabApi/Events/Arguments/Scp079Events/Scp079ChangingCameraEventArgs.cs index b6f14833..eab7b391 100644 --- a/LabApi/Events/Arguments/Scp079Events/Scp079ChangingCameraEventArgs.cs +++ b/LabApi/Events/Arguments/Scp079Events/Scp079ChangingCameraEventArgs.cs @@ -13,11 +13,11 @@ public class Scp079ChangingCameraEventArgs : EventArgs, IPlayerEvent, ICameraEve /// /// Initializes a new instance of the class. /// - /// The SCP-079 player instance. + /// The SCP-079 player instance. /// The affected camera instance. - public Scp079ChangingCameraEventArgs(ReferenceHub player, Scp079Camera camera) + public Scp079ChangingCameraEventArgs(ReferenceHub hub, Scp079Camera camera) { - Player = Player.Get(player); + Player = Player.Get(hub); Camera = Camera.Get(camera); IsAllowed = true; } diff --git a/LabApi/Events/Arguments/Scp079Events/Scp079GainedExperienceEventArgs.cs b/LabApi/Events/Arguments/Scp079Events/Scp079GainedExperienceEventArgs.cs index be6aba7a..d000e3ad 100644 --- a/LabApi/Events/Arguments/Scp079Events/Scp079GainedExperienceEventArgs.cs +++ b/LabApi/Events/Arguments/Scp079Events/Scp079GainedExperienceEventArgs.cs @@ -1,7 +1,9 @@ using LabApi.Events.Arguments.Interfaces; using LabApi.Features.Wrappers; +using PlayerRoles; using PlayerRoles.PlayableScps.Scp079; using System; +using UnityEngine; namespace LabApi.Events.Arguments.Scp079Events; @@ -13,14 +15,16 @@ public class Scp079GainedExperienceEventArgs : EventArgs, IPlayerEvent /// /// Initializes a new instance of the class. /// - /// The SCP-079 player instance. + /// The SCP-079 player instance. /// The amount of experience gained. /// The reason of experience gain shown in HUD. - public Scp079GainedExperienceEventArgs(ReferenceHub player, float amount, Scp079HudTranslation reason) + /// The optional subject of the notification, used as replacement to display which class has been terminated. + public Scp079GainedExperienceEventArgs(ReferenceHub hub, float amount, Scp079HudTranslation reason, RoleTypeId subject) { - Player = Player.Get(player); + Player = Player.Get(hub); Amount = amount; Reason = reason; + Subject = subject; } /// @@ -37,4 +41,9 @@ public Scp079GainedExperienceEventArgs(ReferenceHub player, float amount, Scp079 /// The reason of experience gain shown in HUD. /// public Scp079HudTranslation Reason { get; } + + /// + /// Gets optional subject of the notification, used as replacement to display which class has been terminated. + /// + public RoleTypeId Subject { get; } } diff --git a/LabApi/Events/Arguments/Scp079Events/Scp079GainingExperienceEventArgs.cs b/LabApi/Events/Arguments/Scp079Events/Scp079GainingExperienceEventArgs.cs index 787811a1..33435d7e 100644 --- a/LabApi/Events/Arguments/Scp079Events/Scp079GainingExperienceEventArgs.cs +++ b/LabApi/Events/Arguments/Scp079Events/Scp079GainingExperienceEventArgs.cs @@ -1,5 +1,6 @@ using LabApi.Events.Arguments.Interfaces; using LabApi.Features.Wrappers; +using PlayerRoles; using PlayerRoles.PlayableScps.Scp079; using System; @@ -13,31 +14,38 @@ public class Scp079GainingExperienceEventArgs : EventArgs, IPlayerEvent, ICancel /// /// Initializes a new instance of the class. /// - /// The SCP-079 player instance. + /// The SCP-079 player instance. /// The amount of experience that is going to be gained. /// The reason of experience gain that is going to be shown in HUD. - public Scp079GainingExperienceEventArgs(ReferenceHub player, float amount, Scp079HudTranslation reason) + /// The optional subject of the notification, used as replacement to display which class has been terminated. + public Scp079GainingExperienceEventArgs(ReferenceHub hub, float amount, Scp079HudTranslation reason, RoleTypeId subject) { - Player = Player.Get(player); + Player = Player.Get(hub); Amount = amount; Reason = reason; + Subject = subject; IsAllowed = true; } /// - /// The SCP-079 player instance. + /// Gets the SCP-079 player instance. /// public Player Player { get; } /// - /// The amount of experience that is going to be gained. + /// Gets or sets the amount of experience that is going to be gained. /// - public float Amount { get; } + public float Amount { get; set; } /// - /// The reason of experience gain that is going to be shown in HUD. + /// Gets or sets the reason of experience gain that is going to be shown in HUD. /// - public Scp079HudTranslation Reason { get; } + public Scp079HudTranslation Reason { get; set; } + + /// + /// Gets or sets the optional subject of the notification, used as replacement to display which class has been terminated. + /// + public RoleTypeId Subject { get; set; } /// public bool IsAllowed { get; set; } diff --git a/LabApi/Events/Arguments/Scp079Events/Scp079LeveledUpEventArgs.cs b/LabApi/Events/Arguments/Scp079Events/Scp079LeveledUpEventArgs.cs index 2dfabc9a..c7611315 100644 --- a/LabApi/Events/Arguments/Scp079Events/Scp079LeveledUpEventArgs.cs +++ b/LabApi/Events/Arguments/Scp079Events/Scp079LeveledUpEventArgs.cs @@ -12,11 +12,11 @@ public class Scp079LeveledUpEventArgs : EventArgs, IPlayerEvent /// /// Initializes a new instance of the class. /// - /// The SCP-079 player instance. + /// The SCP-079 player instance. /// The new SCP-079's tier. - public Scp079LeveledUpEventArgs(ReferenceHub player, int tier) + public Scp079LeveledUpEventArgs(ReferenceHub hub, int tier) { - Player = Player.Get(player); + Player = Player.Get(hub); Tier = tier; } diff --git a/LabApi/Events/Arguments/Scp079Events/Scp079LevelingUpEventArgs.cs b/LabApi/Events/Arguments/Scp079Events/Scp079LevelingUpEventArgs.cs index 704f5dd1..12988e42 100644 --- a/LabApi/Events/Arguments/Scp079Events/Scp079LevelingUpEventArgs.cs +++ b/LabApi/Events/Arguments/Scp079Events/Scp079LevelingUpEventArgs.cs @@ -12,11 +12,11 @@ public class Scp079LevelingUpEventArgs : EventArgs, IPlayerEvent, ICancellableEv /// /// Initializes a new instance of the class. /// - /// The SCP-079 player instance. + /// The SCP-079 player instance. /// The new SCP-079's tier. - public Scp079LevelingUpEventArgs(ReferenceHub player, int tier) + public Scp079LevelingUpEventArgs(ReferenceHub hub, int tier) { - Player = Player.Get(player); + Player = Player.Get(hub); Tier = tier; IsAllowed = true; } diff --git a/LabApi/Events/Arguments/Scp079Events/Scp079LockedDoorEventArgs.cs b/LabApi/Events/Arguments/Scp079Events/Scp079LockedDoorEventArgs.cs index 112e5afe..03157713 100644 --- a/LabApi/Events/Arguments/Scp079Events/Scp079LockedDoorEventArgs.cs +++ b/LabApi/Events/Arguments/Scp079Events/Scp079LockedDoorEventArgs.cs @@ -1,7 +1,7 @@ -using LabApi.Events.Arguments.Interfaces; +using Interactables.Interobjects.DoorUtils; +using LabApi.Events.Arguments.Interfaces; using LabApi.Features.Wrappers; using System; -using Interactables.Interobjects.DoorUtils; namespace LabApi.Events.Arguments.Scp079Events; @@ -13,11 +13,11 @@ public class Scp079LockedDoorEventArgs : EventArgs, IPlayerEvent, IDoorEvent /// /// Initializes a new instance of the class. /// - /// The SCP-079 player instance. + /// The SCP-079 player instance. /// The affected door instance. - public Scp079LockedDoorEventArgs(ReferenceHub player, DoorVariant door) + public Scp079LockedDoorEventArgs(ReferenceHub hub, DoorVariant door) { - Player = Player.Get(player); + Player = Player.Get(hub); Door = Door.Get(door); } diff --git a/LabApi/Events/Arguments/Scp079Events/Scp079LockedDownRoomEventArgs.cs b/LabApi/Events/Arguments/Scp079Events/Scp079LockedDownRoomEventArgs.cs index 91279f7f..ced4a88b 100644 --- a/LabApi/Events/Arguments/Scp079Events/Scp079LockedDownRoomEventArgs.cs +++ b/LabApi/Events/Arguments/Scp079Events/Scp079LockedDownRoomEventArgs.cs @@ -1,7 +1,7 @@ using LabApi.Events.Arguments.Interfaces; using LabApi.Features.Wrappers; -using System; using MapGeneration; +using System; namespace LabApi.Events.Arguments.Scp079Events; @@ -13,11 +13,11 @@ public class Scp079LockedDownRoomEventArgs : EventArgs, IPlayerEvent, IRoomEvent /// /// Initializes a new instance of the class. /// - /// The SCP-079 player instance. + /// The SCP-079 player instance. /// The affected room instance. - public Scp079LockedDownRoomEventArgs(ReferenceHub player, RoomIdentifier room) + public Scp079LockedDownRoomEventArgs(ReferenceHub hub, RoomIdentifier room) { - Player = Player.Get(player); + Player = Player.Get(hub); Room = Room.Get(room); } diff --git a/LabApi/Events/Arguments/Scp079Events/Scp079LockingDoorEventArgs.cs b/LabApi/Events/Arguments/Scp079Events/Scp079LockingDoorEventArgs.cs index ee1e7802..d63d8cbe 100644 --- a/LabApi/Events/Arguments/Scp079Events/Scp079LockingDoorEventArgs.cs +++ b/LabApi/Events/Arguments/Scp079Events/Scp079LockingDoorEventArgs.cs @@ -1,7 +1,7 @@ -using LabApi.Events.Arguments.Interfaces; +using Interactables.Interobjects.DoorUtils; +using LabApi.Events.Arguments.Interfaces; using LabApi.Features.Wrappers; using System; -using Interactables.Interobjects.DoorUtils; namespace LabApi.Events.Arguments.Scp079Events; @@ -13,11 +13,11 @@ public class Scp079LockingDoorEventArgs : EventArgs, IPlayerEvent, IDoorEvent, I /// /// Initializes a new instance of the class. /// - /// The SCP-079 player instance. + /// The SCP-079 player instance. /// The affected door instance. - public Scp079LockingDoorEventArgs(ReferenceHub player, DoorVariant door) + public Scp079LockingDoorEventArgs(ReferenceHub hub, DoorVariant door) { - Player = Player.Get(player); + Player = Player.Get(hub); Door = Door.Get(door); IsAllowed = true; } diff --git a/LabApi/Events/Arguments/Scp079Events/Scp079LockingDownRoomEventArgs.cs b/LabApi/Events/Arguments/Scp079Events/Scp079LockingDownRoomEventArgs.cs index a0aaa940..b0cd31a0 100644 --- a/LabApi/Events/Arguments/Scp079Events/Scp079LockingDownRoomEventArgs.cs +++ b/LabApi/Events/Arguments/Scp079Events/Scp079LockingDownRoomEventArgs.cs @@ -1,7 +1,7 @@ using LabApi.Events.Arguments.Interfaces; using LabApi.Features.Wrappers; -using System; using MapGeneration; +using System; namespace LabApi.Events.Arguments.Scp079Events; @@ -13,11 +13,11 @@ public class Scp079LockingDownRoomEventArgs : EventArgs, IPlayerEvent, IRoomEven /// /// Initializes a new instance of the class. /// - /// The SCP-079 player instance. + /// The SCP-079 player instance. /// The affected room instance. - public Scp079LockingDownRoomEventArgs(ReferenceHub player, RoomIdentifier room) + public Scp079LockingDownRoomEventArgs(ReferenceHub hub, RoomIdentifier room) { - Player = Player.Get(player); + Player = Player.Get(hub); Room = Room.Get(room); IsAllowed = true; } diff --git a/LabApi/Events/Arguments/Scp079Events/Scp079RecontainedEventArgs.cs b/LabApi/Events/Arguments/Scp079Events/Scp079RecontainedEventArgs.cs index d519be81..7f542f49 100644 --- a/LabApi/Events/Arguments/Scp079Events/Scp079RecontainedEventArgs.cs +++ b/LabApi/Events/Arguments/Scp079Events/Scp079RecontainedEventArgs.cs @@ -12,11 +12,11 @@ public class Scp079RecontainedEventArgs : EventArgs, IPlayerEvent /// /// Initializes a new instance of the class. /// - /// The SCP-079 player instance. + /// The SCP-079 player instance. /// The player who activated the recontainment procedure. - public Scp079RecontainedEventArgs(ReferenceHub player, ReferenceHub? activator) + public Scp079RecontainedEventArgs(ReferenceHub hub, ReferenceHub? activator) { - Player = Player.Get(player); + Player = Player.Get(hub); Activator = Player.Get(activator); } diff --git a/LabApi/Events/Arguments/Scp079Events/Scp079RecontainingEventArgs.cs b/LabApi/Events/Arguments/Scp079Events/Scp079RecontainingEventArgs.cs index 9557b55d..e9bb3311 100644 --- a/LabApi/Events/Arguments/Scp079Events/Scp079RecontainingEventArgs.cs +++ b/LabApi/Events/Arguments/Scp079Events/Scp079RecontainingEventArgs.cs @@ -12,12 +12,12 @@ public class Scp079RecontainingEventArgs : EventArgs, IPlayerEvent, ICancellable /// /// Initializes a new instance of the class. /// - /// THe SCP-079 player instance. + /// THe SCP-079 player instance. /// The player who activated the recontainment procedure. - public Scp079RecontainingEventArgs(ReferenceHub player, ReferenceHub? activator) + public Scp079RecontainingEventArgs(ReferenceHub hub, ReferenceHub? activator) { IsAllowed = true; - Player = Player.Get(player); + Player = Player.Get(hub); Activator = Player.Get(activator); } diff --git a/LabApi/Events/Arguments/Scp079Events/Scp079UnlockedDoorEventArgs.cs b/LabApi/Events/Arguments/Scp079Events/Scp079UnlockedDoorEventArgs.cs index ac2b2128..3dc1b3c2 100644 --- a/LabApi/Events/Arguments/Scp079Events/Scp079UnlockedDoorEventArgs.cs +++ b/LabApi/Events/Arguments/Scp079Events/Scp079UnlockedDoorEventArgs.cs @@ -1,7 +1,7 @@ -using LabApi.Events.Arguments.Interfaces; +using Interactables.Interobjects.DoorUtils; +using LabApi.Events.Arguments.Interfaces; using LabApi.Features.Wrappers; using System; -using Interactables.Interobjects.DoorUtils; namespace LabApi.Events.Arguments.Scp079Events; @@ -13,11 +13,11 @@ public class Scp079UnlockedDoorEventArgs : EventArgs, IPlayerEvent, IDoorEvent /// /// Initializes a new instance of the class. /// - /// The SCP-079 player instance. + /// The SCP-079 player instance. /// The affected door instance. - public Scp079UnlockedDoorEventArgs(ReferenceHub player, DoorVariant door) + public Scp079UnlockedDoorEventArgs(ReferenceHub hub, DoorVariant door) { - Player = Player.Get(player); + Player = Player.Get(hub); Door = Door.Get(door); } diff --git a/LabApi/Events/Arguments/Scp079Events/Scp079UnlockingDoorEventArgs.cs b/LabApi/Events/Arguments/Scp079Events/Scp079UnlockingDoorEventArgs.cs index 9d55ab03..6bfa3e9e 100644 --- a/LabApi/Events/Arguments/Scp079Events/Scp079UnlockingDoorEventArgs.cs +++ b/LabApi/Events/Arguments/Scp079Events/Scp079UnlockingDoorEventArgs.cs @@ -1,7 +1,7 @@ -using LabApi.Events.Arguments.Interfaces; +using Interactables.Interobjects.DoorUtils; +using LabApi.Events.Arguments.Interfaces; using LabApi.Features.Wrappers; using System; -using Interactables.Interobjects.DoorUtils; namespace LabApi.Events.Arguments.Scp079Events; @@ -13,11 +13,11 @@ public class Scp079UnlockingDoorEventArgs : EventArgs, IPlayerEvent, IDoorEvent, /// /// Initializes a new instance of the class. /// - /// The SCP-079 player instance. + /// The SCP-079 player instance. /// The affected door instance. - public Scp079UnlockingDoorEventArgs(ReferenceHub player, DoorVariant door) + public Scp079UnlockingDoorEventArgs(ReferenceHub hub, DoorVariant door) { - Player = Player.Get(player); + Player = Player.Get(hub); Door = Door.Get(door); IsAllowed = true; } diff --git a/LabApi/Events/Arguments/Scp079Events/Scp079UsedTeslaEventArgs.cs b/LabApi/Events/Arguments/Scp079Events/Scp079UsedTeslaEventArgs.cs index ff26e05d..ee07d1c9 100644 --- a/LabApi/Events/Arguments/Scp079Events/Scp079UsedTeslaEventArgs.cs +++ b/LabApi/Events/Arguments/Scp079Events/Scp079UsedTeslaEventArgs.cs @@ -12,11 +12,11 @@ public class Scp079UsedTeslaEventArgs : EventArgs, IPlayerEvent, ITeslaEvent /// /// Initializes a new instance of the class. /// - /// The SCP-079 player instance. + /// The SCP-079 player instance. /// The affected tesla instance. - public Scp079UsedTeslaEventArgs(ReferenceHub player, TeslaGate tesla) + public Scp079UsedTeslaEventArgs(ReferenceHub hub, TeslaGate tesla) { - Player = Player.Get(player); + Player = Player.Get(hub); Tesla = Tesla.Get(tesla); } @@ -24,7 +24,7 @@ public Scp079UsedTeslaEventArgs(ReferenceHub player, TeslaGate tesla) /// The SCP-079 player instance. /// public Player Player { get; } - + /// public Tesla Tesla { get; } } diff --git a/LabApi/Events/Arguments/Scp079Events/Scp079UsingTeslaEventArgs.cs b/LabApi/Events/Arguments/Scp079Events/Scp079UsingTeslaEventArgs.cs index fc4da733..41c31b69 100644 --- a/LabApi/Events/Arguments/Scp079Events/Scp079UsingTeslaEventArgs.cs +++ b/LabApi/Events/Arguments/Scp079Events/Scp079UsingTeslaEventArgs.cs @@ -12,11 +12,11 @@ public class Scp079UsingTeslaEventArgs : EventArgs, IPlayerEvent, ITeslaEvent, I /// /// Initializes a new instance of the class. /// - /// The SCP-079 player instance. + /// The SCP-079 player instance. /// The affected tesla instance. - public Scp079UsingTeslaEventArgs(ReferenceHub player, TeslaGate tesla) + public Scp079UsingTeslaEventArgs(ReferenceHub hub, TeslaGate tesla) { - Player = Player.Get(player); + Player = Player.Get(hub); Tesla = Tesla.Get(tesla); IsAllowed = true; } diff --git a/LabApi/Events/Arguments/Scp096Events/Scp096AddedTargetEventArgs.cs b/LabApi/Events/Arguments/Scp096Events/Scp096AddedTargetEventArgs.cs index b90adbe1..a17c23fb 100644 --- a/LabApi/Events/Arguments/Scp096Events/Scp096AddedTargetEventArgs.cs +++ b/LabApi/Events/Arguments/Scp096Events/Scp096AddedTargetEventArgs.cs @@ -12,12 +12,12 @@ public class Scp096AddedTargetEventArgs : EventArgs, IPlayerEvent, ITargetEvent /// /// Initializes a new instance of the class. /// - /// The SCP-096 player instance. + /// The SCP-096 player instance. /// The target player instance. /// Whether the target looked at SCP-096. - public Scp096AddedTargetEventArgs(ReferenceHub player, ReferenceHub target, bool wasLooking) + public Scp096AddedTargetEventArgs(ReferenceHub hub, ReferenceHub target, bool wasLooking) { - Player = Player.Get(player); + Player = Player.Get(hub); Target = Player.Get(target); WasLooking = wasLooking; } @@ -33,7 +33,7 @@ public Scp096AddedTargetEventArgs(ReferenceHub player, ReferenceHub target, bool public Player Target { get; } /// - /// Whether the target was looking at SCP-096 + /// Whether the target was looking at SCP-096. /// public bool WasLooking { get; } } diff --git a/LabApi/Events/Arguments/Scp096Events/Scp096AddingTargetEventArgs.cs b/LabApi/Events/Arguments/Scp096Events/Scp096AddingTargetEventArgs.cs index afc74b28..2bbc125b 100644 --- a/LabApi/Events/Arguments/Scp096Events/Scp096AddingTargetEventArgs.cs +++ b/LabApi/Events/Arguments/Scp096Events/Scp096AddingTargetEventArgs.cs @@ -12,12 +12,12 @@ public class Scp096AddingTargetEventArgs : EventArgs, IPlayerEvent, ITargetEvent /// /// Initializes a new instance of the class. /// - /// The SCP-096 player instance. + /// The SCP-096 player instance. /// The target player instance. /// Whether the target looked at SCP-096. - public Scp096AddingTargetEventArgs(ReferenceHub player, ReferenceHub target, bool wasLooking) + public Scp096AddingTargetEventArgs(ReferenceHub hub, ReferenceHub target, bool wasLooking) { - Player = Player.Get(player); + Player = Player.Get(hub); Target = Player.Get(target); WasLooking = wasLooking; IsAllowed = true; @@ -34,7 +34,7 @@ public Scp096AddingTargetEventArgs(ReferenceHub player, ReferenceHub target, boo public Player Target { get; } /// - /// Whether the target was looking at SCP-096 + /// Whether the target was looking at SCP-096. /// public bool WasLooking { get; } diff --git a/LabApi/Events/Arguments/Scp096Events/Scp096ChangedStateEventArgs.cs b/LabApi/Events/Arguments/Scp096Events/Scp096ChangedStateEventArgs.cs index ac457100..eaa7c5f9 100644 --- a/LabApi/Events/Arguments/Scp096Events/Scp096ChangedStateEventArgs.cs +++ b/LabApi/Events/Arguments/Scp096Events/Scp096ChangedStateEventArgs.cs @@ -13,11 +13,11 @@ public class Scp096ChangedStateEventArgs : EventArgs, IPlayerEvent /// /// Initializes a new instance of the class. /// - /// The SCP-096 player instance. + /// The SCP-096 player instance. /// The SCP-096's new rage state. - public Scp096ChangedStateEventArgs(ReferenceHub player, Scp096RageState state) + public Scp096ChangedStateEventArgs(ReferenceHub hub, Scp096RageState state) { - Player = Player.Get(player); + Player = Player.Get(hub); State = state; } diff --git a/LabApi/Events/Arguments/Scp096Events/Scp096ChangingStateEventArgs.cs b/LabApi/Events/Arguments/Scp096Events/Scp096ChangingStateEventArgs.cs index d0e984f2..00304ecd 100644 --- a/LabApi/Events/Arguments/Scp096Events/Scp096ChangingStateEventArgs.cs +++ b/LabApi/Events/Arguments/Scp096Events/Scp096ChangingStateEventArgs.cs @@ -13,11 +13,11 @@ public class Scp096ChangingStateEventArgs : EventArgs, IPlayerEvent, ICancellabl /// /// Initializes a new instance of the class. /// - /// The SCP-096 player instance. + /// The SCP-096 player instance. /// The SCP-096's new rage state. - public Scp096ChangingStateEventArgs(ReferenceHub player, Scp096RageState state) + public Scp096ChangingStateEventArgs(ReferenceHub hub, Scp096RageState state) { - Player = Player.Get(player); + Player = Player.Get(hub); State = state; IsAllowed = true; } diff --git a/LabApi/Events/Arguments/Scp096Events/Scp096ChargedEventArgs.cs b/LabApi/Events/Arguments/Scp096Events/Scp096ChargedEventArgs.cs index 013ba81c..88affc05 100644 --- a/LabApi/Events/Arguments/Scp096Events/Scp096ChargedEventArgs.cs +++ b/LabApi/Events/Arguments/Scp096Events/Scp096ChargedEventArgs.cs @@ -12,10 +12,10 @@ public class Scp096ChargedEventArgs : EventArgs, IPlayerEvent /// /// Initializes a new instance of the class. /// - /// The SCP-096 player instance. - public Scp096ChargedEventArgs(ReferenceHub player) + /// The SCP-096 player instance. + public Scp096ChargedEventArgs(ReferenceHub hub) { - Player = Player.Get(player); + Player = Player.Get(hub); } /// diff --git a/LabApi/Events/Arguments/Scp096Events/Scp096ChargingEventArgs.cs b/LabApi/Events/Arguments/Scp096Events/Scp096ChargingEventArgs.cs index b5849b11..1fd348da 100644 --- a/LabApi/Events/Arguments/Scp096Events/Scp096ChargingEventArgs.cs +++ b/LabApi/Events/Arguments/Scp096Events/Scp096ChargingEventArgs.cs @@ -12,10 +12,10 @@ public class Scp096ChargingEventArgs : EventArgs, IPlayerEvent, ICancellableEven /// /// Initializes a new instance of the class. /// - /// The SCP-096 player instance. - public Scp096ChargingEventArgs(ReferenceHub player) + /// The SCP-096 player instance. + public Scp096ChargingEventArgs(ReferenceHub hub) { - Player = Player.Get(player); + Player = Player.Get(hub); IsAllowed = true; } diff --git a/LabApi/Events/Arguments/Scp096Events/Scp096EnragedEventArgs.cs b/LabApi/Events/Arguments/Scp096Events/Scp096EnragedEventArgs.cs index 330472a5..19709ebf 100644 --- a/LabApi/Events/Arguments/Scp096Events/Scp096EnragedEventArgs.cs +++ b/LabApi/Events/Arguments/Scp096Events/Scp096EnragedEventArgs.cs @@ -12,11 +12,11 @@ public class Scp096EnragedEventArgs : EventArgs, IPlayerEvent /// /// Initializes a new instance of the class. /// - /// The SCP-096 player instance. + /// The SCP-096 player instance. /// The initial duration of the rage. - public Scp096EnragedEventArgs(ReferenceHub player, float initialDuration) + public Scp096EnragedEventArgs(ReferenceHub hub, float initialDuration) { - Player = Player.Get(player); + Player = Player.Get(hub); InitialDuration = initialDuration; } diff --git a/LabApi/Events/Arguments/Scp096Events/Scp096EnragingEventArgs.cs b/LabApi/Events/Arguments/Scp096Events/Scp096EnragingEventArgs.cs index 21ff5fce..8b51af12 100644 --- a/LabApi/Events/Arguments/Scp096Events/Scp096EnragingEventArgs.cs +++ b/LabApi/Events/Arguments/Scp096Events/Scp096EnragingEventArgs.cs @@ -12,11 +12,11 @@ public class Scp096EnragingEventArgs : EventArgs, IPlayerEvent, ICancellableEven /// /// Initializes a new instance of the class. /// - /// The SCP-096 player instance. + /// The SCP-096 player instance. /// The initial duration of the rage. - public Scp096EnragingEventArgs(ReferenceHub player, float initialDuration) + public Scp096EnragingEventArgs(ReferenceHub hub, float initialDuration) { - Player = Player.Get(player); + Player = Player.Get(hub); InitialDuration = initialDuration; IsAllowed = true; } diff --git a/LabApi/Events/Arguments/Scp096Events/Scp096PriedGateEventArgs.cs b/LabApi/Events/Arguments/Scp096Events/Scp096PriedGateEventArgs.cs index c7315e6d..f7c5fd06 100644 --- a/LabApi/Events/Arguments/Scp096Events/Scp096PriedGateEventArgs.cs +++ b/LabApi/Events/Arguments/Scp096Events/Scp096PriedGateEventArgs.cs @@ -13,11 +13,11 @@ public class Scp096PriedGateEventArgs : EventArgs, IPlayerEvent, IGateEvent /// /// Initializes a new instance of the class. /// - /// The SCP-096 player instance. + /// The SCP-096 player instance. /// The affected pryable door instance. - public Scp096PriedGateEventArgs(ReferenceHub player, PryableDoor gate) + public Scp096PriedGateEventArgs(ReferenceHub hub, PryableDoor gate) { - Player = Player.Get(player); + Player = Player.Get(hub); Gate = Gate.Get(gate); } diff --git a/LabApi/Events/Arguments/Scp096Events/Scp096PryingGateEventArgs.cs b/LabApi/Events/Arguments/Scp096Events/Scp096PryingGateEventArgs.cs index aab475f7..2e225423 100644 --- a/LabApi/Events/Arguments/Scp096Events/Scp096PryingGateEventArgs.cs +++ b/LabApi/Events/Arguments/Scp096Events/Scp096PryingGateEventArgs.cs @@ -13,11 +13,11 @@ public class Scp096PryingGateEventArgs : EventArgs, IPlayerEvent, IGateEvent, IC /// /// Initializes a new instance of the class. /// - /// The SCP-096 player instance. + /// The SCP-096 player instance. /// The affected pryable door instance. - public Scp096PryingGateEventArgs(ReferenceHub player, PryableDoor gate) + public Scp096PryingGateEventArgs(ReferenceHub hub, PryableDoor gate) { - Player = Player.Get(player); + Player = Player.Get(hub); Gate = Gate.Get(gate); IsAllowed = true; } diff --git a/LabApi/Events/Arguments/Scp096Events/Scp096StartCryingEventArgs.cs b/LabApi/Events/Arguments/Scp096Events/Scp096StartCryingEventArgs.cs index 8b50efaf..82580883 100644 --- a/LabApi/Events/Arguments/Scp096Events/Scp096StartCryingEventArgs.cs +++ b/LabApi/Events/Arguments/Scp096Events/Scp096StartCryingEventArgs.cs @@ -12,10 +12,10 @@ public class Scp096StartCryingEventArgs : EventArgs, IPlayerEvent, ICancellableE /// /// Initializes a new instance of the class. /// - /// The SCP-096 player instance. - public Scp096StartCryingEventArgs(ReferenceHub player) + /// The SCP-096 player instance. + public Scp096StartCryingEventArgs(ReferenceHub hub) { - Player = Player.Get(player); + Player = Player.Get(hub); IsAllowed = true; } diff --git a/LabApi/Events/Arguments/Scp096Events/Scp096StartedCryingEventArgs.cs b/LabApi/Events/Arguments/Scp096Events/Scp096StartedCryingEventArgs.cs index e1dcede8..69aedd7a 100644 --- a/LabApi/Events/Arguments/Scp096Events/Scp096StartedCryingEventArgs.cs +++ b/LabApi/Events/Arguments/Scp096Events/Scp096StartedCryingEventArgs.cs @@ -12,10 +12,10 @@ public class Scp096StartedCryingEventArgs : EventArgs, IPlayerEvent /// /// Initializes a new instance of the class. /// - /// The SCP-096 player instance. - public Scp096StartedCryingEventArgs(ReferenceHub player) + /// The SCP-096 player instance. + public Scp096StartedCryingEventArgs(ReferenceHub hub) { - Player = Player.Get(player); + Player = Player.Get(hub); } /// diff --git a/LabApi/Events/Arguments/Scp096Events/Scp096TriedNotToCryEventArgs.cs b/LabApi/Events/Arguments/Scp096Events/Scp096TriedNotToCryEventArgs.cs index 22fe4195..76b72dee 100644 --- a/LabApi/Events/Arguments/Scp096Events/Scp096TriedNotToCryEventArgs.cs +++ b/LabApi/Events/Arguments/Scp096Events/Scp096TriedNotToCryEventArgs.cs @@ -12,10 +12,10 @@ public class Scp096TriedNotToCryEventArgs : EventArgs, IPlayerEvent /// /// Initializes a new instance of the class. /// - /// The SCP-096 player instance. - public Scp096TriedNotToCryEventArgs(ReferenceHub player) + /// The SCP-096 player instance. + public Scp096TriedNotToCryEventArgs(ReferenceHub hub) { - Player = Player.Get(player); + Player = Player.Get(hub); } /// diff --git a/LabApi/Events/Arguments/Scp096Events/Scp096TryingNotToCryEventArgs.cs b/LabApi/Events/Arguments/Scp096Events/Scp096TryingNotToCryEventArgs.cs index 7fb220b1..73428db7 100644 --- a/LabApi/Events/Arguments/Scp096Events/Scp096TryingNotToCryEventArgs.cs +++ b/LabApi/Events/Arguments/Scp096Events/Scp096TryingNotToCryEventArgs.cs @@ -12,10 +12,10 @@ public class Scp096TryingNotToCryEventArgs : EventArgs, IPlayerEvent, ICancellab /// /// Initializes a new instance of the class. /// - /// The SCP-096 player instance. - public Scp096TryingNotToCryEventArgs(ReferenceHub player) + /// The SCP-096 player instance. + public Scp096TryingNotToCryEventArgs(ReferenceHub hub) { - Player = Player.Get(player); + Player = Player.Get(hub); IsAllowed = true; } diff --git a/LabApi/Events/Arguments/Scp106Events/Scp106ChangedStalkModeEventArgs.cs b/LabApi/Events/Arguments/Scp106Events/Scp106ChangedStalkModeEventArgs.cs index 0fdca5de..8a4d8bc4 100644 --- a/LabApi/Events/Arguments/Scp106Events/Scp106ChangedStalkModeEventArgs.cs +++ b/LabApi/Events/Arguments/Scp106Events/Scp106ChangedStalkModeEventArgs.cs @@ -1,6 +1,6 @@ -using System; using LabApi.Events.Arguments.Interfaces; using LabApi.Features.Wrappers; +using System; namespace LabApi.Events.Arguments.Scp106Events; @@ -12,19 +12,19 @@ public class Scp106ChangedStalkModeEventArgs : EventArgs, IPlayerEvent /// /// Initializes a new instance of the class. /// - /// The SCP-106 player instance. + /// The SCP-106 player instance. /// Whether the ability was activated or deactivated. - public Scp106ChangedStalkModeEventArgs(ReferenceHub player, bool active) + public Scp106ChangedStalkModeEventArgs(ReferenceHub hub, bool active) { - Player = Player.Get(player); + Player = Player.Get(hub); IsStalkActive = active; } - + /// /// Whether the ability was activated or deactivated. /// public bool IsStalkActive { get; } - + /// /// The SCP-106 player instance. /// diff --git a/LabApi/Events/Arguments/Scp106Events/Scp106ChangedSubmersionStatusEventArgs.cs b/LabApi/Events/Arguments/Scp106Events/Scp106ChangedSubmersionStatusEventArgs.cs index d2645590..7414dee0 100644 --- a/LabApi/Events/Arguments/Scp106Events/Scp106ChangedSubmersionStatusEventArgs.cs +++ b/LabApi/Events/Arguments/Scp106Events/Scp106ChangedSubmersionStatusEventArgs.cs @@ -1,6 +1,6 @@ -using System; using LabApi.Events.Arguments.Interfaces; using LabApi.Features.Wrappers; +using System; namespace LabApi.Events.Arguments.Scp106Events; @@ -12,19 +12,19 @@ public class Scp106ChangedSubmersionStatusEventArgs : EventArgs, IPlayerEvent /// /// Initializes a new instance of the class. /// - /// The SCP-106 player instance. + /// The SCP-106 player instance. /// Whether the SCP-106 is submerging or emerging. - public Scp106ChangedSubmersionStatusEventArgs(ReferenceHub player, bool isSubmerging) + public Scp106ChangedSubmersionStatusEventArgs(ReferenceHub hub, bool isSubmerging) { - Player = Player.Get(player); + Player = Player.Get(hub); IsSubmerging = isSubmerging; } - + /// /// Whether the SCP-106 is submerging or emerging. /// public bool IsSubmerging { get; } - + /// /// The SCP-106 player instance. /// diff --git a/LabApi/Events/Arguments/Scp106Events/Scp106ChangedVigorEventArgs.cs b/LabApi/Events/Arguments/Scp106Events/Scp106ChangedVigorEventArgs.cs index a94ed84b..fc65953b 100644 --- a/LabApi/Events/Arguments/Scp106Events/Scp106ChangedVigorEventArgs.cs +++ b/LabApi/Events/Arguments/Scp106Events/Scp106ChangedVigorEventArgs.cs @@ -1,6 +1,6 @@ -using System; using LabApi.Events.Arguments.Interfaces; using LabApi.Features.Wrappers; +using System; namespace LabApi.Events.Arguments.Scp106Events; @@ -12,12 +12,12 @@ public class Scp106ChangedVigorEventArgs : EventArgs, IPlayerEvent /// /// Initializes a new instance of the class. /// - /// The SCP-106 player instance. + /// The SCP-106 player instance. /// The previous vigor value. /// The new vigor value. - public Scp106ChangedVigorEventArgs(ReferenceHub player, float oldVigor, float newVigor) + public Scp106ChangedVigorEventArgs(ReferenceHub hub, float oldVigor, float newVigor) { - Player = Player.Get(player); + Player = Player.Get(hub); OldValue = oldVigor; Value = newVigor; } diff --git a/LabApi/Events/Arguments/Scp106Events/Scp106ChangingStalkModeEventArgs.cs b/LabApi/Events/Arguments/Scp106Events/Scp106ChangingStalkModeEventArgs.cs index dbf5be08..cbe7ac71 100644 --- a/LabApi/Events/Arguments/Scp106Events/Scp106ChangingStalkModeEventArgs.cs +++ b/LabApi/Events/Arguments/Scp106Events/Scp106ChangingStalkModeEventArgs.cs @@ -1,6 +1,6 @@ -using System; using LabApi.Events.Arguments.Interfaces; using LabApi.Features.Wrappers; +using System; namespace LabApi.Events.Arguments.Scp106Events; @@ -12,25 +12,25 @@ public class Scp106ChangingStalkModeEventArgs : EventArgs, IPlayerEvent, ICancel /// /// Initializes a new instance of the class. /// - /// The SCP-106 player instance. + /// The SCP-106 player instance. /// Whether the ability is being activated or deactivated. - public Scp106ChangingStalkModeEventArgs(ReferenceHub player, bool active) + public Scp106ChangingStalkModeEventArgs(ReferenceHub hub, bool active) { IsAllowed = true; - Player = Player.Get(player); + Player = Player.Get(hub); IsStalkActive = active; } - + /// /// Whether the ability is being activated or deactivated. /// public bool IsStalkActive { get; } - + /// /// The SCP-106 player instance. /// public Player Player { get; } - + /// public bool IsAllowed { get; set; } } \ No newline at end of file diff --git a/LabApi/Events/Arguments/Scp106Events/Scp106ChangingSubmersionStatusEventArgs.cs b/LabApi/Events/Arguments/Scp106Events/Scp106ChangingSubmersionStatusEventArgs.cs index ad9b800f..3dfe5fea 100644 --- a/LabApi/Events/Arguments/Scp106Events/Scp106ChangingSubmersionStatusEventArgs.cs +++ b/LabApi/Events/Arguments/Scp106Events/Scp106ChangingSubmersionStatusEventArgs.cs @@ -1,6 +1,6 @@ -using System; using LabApi.Events.Arguments.Interfaces; using LabApi.Features.Wrappers; +using System; namespace LabApi.Events.Arguments.Scp106Events; @@ -12,11 +12,11 @@ public class Scp106ChangingSubmersionStatusEventArgs : EventArgs, IPlayerEvent, /// /// Initializes a new instance of the class. /// - /// The SCP-106 player instance. + /// The SCP-106 player instance. /// Whether the SCP-106 is submerging or emerging. - public Scp106ChangingSubmersionStatusEventArgs(ReferenceHub player, bool isSubmerging) + public Scp106ChangingSubmersionStatusEventArgs(ReferenceHub hub, bool isSubmerging) { - Player = Player.Get(player); + Player = Player.Get(hub); IsSubmerging = isSubmerging; IsAllowed = true; } diff --git a/LabApi/Events/Arguments/Scp106Events/Scp106ChangingVigorEventArgs.cs b/LabApi/Events/Arguments/Scp106Events/Scp106ChangingVigorEventArgs.cs index bc174da0..19ddee11 100644 --- a/LabApi/Events/Arguments/Scp106Events/Scp106ChangingVigorEventArgs.cs +++ b/LabApi/Events/Arguments/Scp106Events/Scp106ChangingVigorEventArgs.cs @@ -1,6 +1,6 @@ -using System; using LabApi.Events.Arguments.Interfaces; using LabApi.Features.Wrappers; +using System; namespace LabApi.Events.Arguments.Scp106Events; @@ -12,12 +12,12 @@ public class Scp106ChangingVigorEventArgs : EventArgs, IPlayerEvent, ICancellabl /// /// Initializes a new instance of the class. /// - /// The SCP-106 player instance. + /// The SCP-106 player instance. /// The previous vigor value. /// The new vigor value. - public Scp106ChangingVigorEventArgs(ReferenceHub player, float oldValue, float value) + public Scp106ChangingVigorEventArgs(ReferenceHub hub, float oldValue, float value) { - Player = Player.Get(player); + Player = Player.Get(hub); OldValue = oldValue; Value = value; IsAllowed = true; diff --git a/LabApi/Events/Arguments/Scp106Events/Scp106TeleportedPlayerEvent.cs b/LabApi/Events/Arguments/Scp106Events/Scp106TeleportedPlayerEvent.cs index a8e2f397..5041bbb4 100644 --- a/LabApi/Events/Arguments/Scp106Events/Scp106TeleportedPlayerEvent.cs +++ b/LabApi/Events/Arguments/Scp106Events/Scp106TeleportedPlayerEvent.cs @@ -1,6 +1,6 @@ -using System; -using LabApi.Events.Arguments.Interfaces; +using LabApi.Events.Arguments.Interfaces; using LabApi.Features.Wrappers; +using System; namespace LabApi.Events.Arguments.Scp106Events; @@ -12,11 +12,11 @@ public class Scp106TeleportedPlayerEvent : EventArgs, IPlayerEvent, ITargetEvent /// /// Initializes a new instance of the class. /// - /// The SCP-106 player instance. + /// The SCP-106 player instance. /// The player that was teleported. - public Scp106TeleportedPlayerEvent(ReferenceHub player, ReferenceHub target) + public Scp106TeleportedPlayerEvent(ReferenceHub hub, ReferenceHub target) { - Player = Player.Get(player); + Player = Player.Get(hub); Target = Player.Get(target); } diff --git a/LabApi/Events/Arguments/Scp106Events/Scp106TeleportingPlayerEvent.cs b/LabApi/Events/Arguments/Scp106Events/Scp106TeleportingPlayerEvent.cs index 29de2333..2c9bf1d1 100644 --- a/LabApi/Events/Arguments/Scp106Events/Scp106TeleportingPlayerEvent.cs +++ b/LabApi/Events/Arguments/Scp106Events/Scp106TeleportingPlayerEvent.cs @@ -1,6 +1,6 @@ -using System; -using LabApi.Events.Arguments.Interfaces; +using LabApi.Events.Arguments.Interfaces; using LabApi.Features.Wrappers; +using System; namespace LabApi.Events.Arguments.Scp106Events; @@ -12,12 +12,12 @@ public class Scp106TeleportingPlayerEvent : EventArgs, IPlayerEvent, ITargetEven /// /// Initializes a new instance of the class. /// - /// The SCP-106 player instance. + /// The SCP-106 player instance. /// The player that is being teleported. - public Scp106TeleportingPlayerEvent(ReferenceHub player, ReferenceHub target) + public Scp106TeleportingPlayerEvent(ReferenceHub hub, ReferenceHub target) { IsAllowed = true; - Player = Player.Get(player); + Player = Player.Get(hub); Target = Player.Get(target); } diff --git a/LabApi/Events/Arguments/Scp106Events/Scp106UsedHunterAtlasEventArgs.cs b/LabApi/Events/Arguments/Scp106Events/Scp106UsedHunterAtlasEventArgs.cs index 7fac8b7c..82ad3d05 100644 --- a/LabApi/Events/Arguments/Scp106Events/Scp106UsedHunterAtlasEventArgs.cs +++ b/LabApi/Events/Arguments/Scp106Events/Scp106UsedHunterAtlasEventArgs.cs @@ -1,6 +1,6 @@ -using System; using LabApi.Events.Arguments.Interfaces; using LabApi.Features.Wrappers; +using System; using UnityEngine; namespace LabApi.Events.Arguments.Scp106Events; @@ -13,11 +13,11 @@ public class Scp106UsedHunterAtlasEventArgs : EventArgs, IPlayerEvent /// /// Initializes a new instance of the class. /// - /// The SCP-106 player instance. + /// The SCP-106 player instance. /// The original position. - public Scp106UsedHunterAtlasEventArgs(ReferenceHub player, Vector3 originalPosition) + public Scp106UsedHunterAtlasEventArgs(ReferenceHub hub, Vector3 originalPosition) { - Player = Player.Get(player); + Player = Player.Get(hub); OriginalPosition = originalPosition; } diff --git a/LabApi/Events/Arguments/Scp106Events/Scp106UsingHunterAtlasEventArgs.cs b/LabApi/Events/Arguments/Scp106Events/Scp106UsingHunterAtlasEventArgs.cs index 294699da..7cad26d6 100644 --- a/LabApi/Events/Arguments/Scp106Events/Scp106UsingHunterAtlasEventArgs.cs +++ b/LabApi/Events/Arguments/Scp106Events/Scp106UsingHunterAtlasEventArgs.cs @@ -1,6 +1,6 @@ -using System; using LabApi.Events.Arguments.Interfaces; using LabApi.Features.Wrappers; +using System; using UnityEngine; namespace LabApi.Events.Arguments.Scp106Events; @@ -13,11 +13,11 @@ public class Scp106UsingHunterAtlasEventArgs : EventArgs, IPlayerEvent, ICancell /// /// Initializes a new instance of the class. /// - /// The SCP-106 player instance. + /// The SCP-106 player instance. /// The destination position. - public Scp106UsingHunterAtlasEventArgs(ReferenceHub player, Vector3 destinationPosition) + public Scp106UsingHunterAtlasEventArgs(ReferenceHub hub, Vector3 destinationPosition) { - Player = Player.Get(player); + Player = Player.Get(hub); DestinationPosition = destinationPosition; IsAllowed = true; } diff --git a/LabApi/Events/Arguments/Scp127Events/Scp127GainExperienceEventArgs.cs b/LabApi/Events/Arguments/Scp127Events/Scp127GainExperienceEventArgs.cs new file mode 100644 index 00000000..2e15869f --- /dev/null +++ b/LabApi/Events/Arguments/Scp127Events/Scp127GainExperienceEventArgs.cs @@ -0,0 +1,34 @@ +using InventorySystem.Items.Firearms; +using LabApi.Events.Arguments.Interfaces; +using LabApi.Events.Arguments.Scp127Events; +using LabApi.Features.Wrappers; +using System; + +namespace LabApi.Events.Arguments.Scp127Events; + +/// +/// Represents the arguments for the event. +/// +public class Scp127GainExperienceEventArgs : EventArgs, IScp127ItemEvent +{ + /// + /// Initializes a new instance of the class. + /// + /// The Scp-127 firearm. + /// The gained experience. + public Scp127GainExperienceEventArgs(Firearm weapon, float exp) + { + Scp127Item = (Scp127Firearm)FirearmItem.Get(weapon); + ExperienceGain = exp; + } + + /// + /// Gets the SCP-127 firearm. + /// + public Scp127Firearm Scp127Item { get; } + + /// + /// Gets the amount of experience the SCP-127 gained. + /// + public float ExperienceGain { get; } +} diff --git a/LabApi/Events/Arguments/Scp127Events/Scp127GainingExperienceEventArgs.cs b/LabApi/Events/Arguments/Scp127Events/Scp127GainingExperienceEventArgs.cs new file mode 100644 index 00000000..2bec197f --- /dev/null +++ b/LabApi/Events/Arguments/Scp127Events/Scp127GainingExperienceEventArgs.cs @@ -0,0 +1,37 @@ +using InventorySystem.Items.Firearms; +using LabApi.Events.Arguments.Interfaces; +using LabApi.Features.Wrappers; +using System; + +namespace LabApi.Events.Arguments.Scp127Events; + +/// +/// Represents the arguments for the event. +/// +public class Scp127GainingExperienceEventArgs : EventArgs, IScp127ItemEvent, ICancellableEvent +{ + /// + /// Initializes a new instance of the class. + /// + /// The Scp-127 firearm. + /// The experience to be gained. + public Scp127GainingExperienceEventArgs(Firearm weapon, float exp) + { + Scp127Item = (Scp127Firearm)FirearmItem.Get(weapon); + ExperienceGain = exp; + IsAllowed = true; + } + + /// + /// Gets the SCP-127 firearm. + /// + public Scp127Firearm Scp127Item { get; } + + /// + /// Gets or sets the amount of experience the SCP-127 will gain. + /// + public float ExperienceGain { get; set; } + + /// + public bool IsAllowed { get; set; } +} diff --git a/LabApi/Events/Arguments/Scp127Events/Scp127LevelUpEventArgs.cs b/LabApi/Events/Arguments/Scp127Events/Scp127LevelUpEventArgs.cs new file mode 100644 index 00000000..2fd9baf5 --- /dev/null +++ b/LabApi/Events/Arguments/Scp127Events/Scp127LevelUpEventArgs.cs @@ -0,0 +1,34 @@ +using InventorySystem.Items.Firearms; +using InventorySystem.Items.Firearms.Modules.Scp127; +using LabApi.Events.Arguments.Interfaces; +using LabApi.Features.Wrappers; +using System; + +namespace LabApi.Events.Arguments.Scp127Events; + +/// +/// Represents the arguments for the event. +/// +public class Scp127LevelUpEventArgs : EventArgs, IScp127ItemEvent +{ + /// + /// Initializes a new instance of the class. + /// + /// The Scp-127 firearm. + /// The new tier. + public Scp127LevelUpEventArgs(Firearm weapon, Scp127Tier tier) + { + Scp127Item = (Scp127Firearm)FirearmItem.Get(weapon); + Tier = tier; + } + + /// + /// Gets the SCP-127 firearm. + /// + public Scp127Firearm Scp127Item { get; } + + /// + /// Gets the new tier of SCP-127. + /// + public Scp127Tier Tier { get; } +} diff --git a/LabApi/Events/Arguments/Scp127Events/Scp127LevellingUpEventArgs.cs b/LabApi/Events/Arguments/Scp127Events/Scp127LevellingUpEventArgs.cs new file mode 100644 index 00000000..f412e379 --- /dev/null +++ b/LabApi/Events/Arguments/Scp127Events/Scp127LevellingUpEventArgs.cs @@ -0,0 +1,38 @@ +using InventorySystem.Items.Firearms; +using InventorySystem.Items.Firearms.Modules.Scp127; +using LabApi.Events.Arguments.Interfaces; +using LabApi.Features.Wrappers; +using System; + +namespace LabApi.Events.Arguments.Scp127Events; + +/// +/// Represents the arguments for the event. +/// +public class Scp127LevellingUpEventArgs : EventArgs, IScp127ItemEvent, ICancellableEvent +{ + /// + /// Initializes a new instance of the class. + /// + /// The Scp-127 firearm. + /// The new tier. + public Scp127LevellingUpEventArgs(Firearm weapon, Scp127Tier tier) + { + Scp127Item = (Scp127Firearm)FirearmItem.Get(weapon); + Tier = tier; + IsAllowed = true; + } + + /// + /// Gets the SCP-127 firearm. + /// + public Scp127Firearm Scp127Item { get; } + + /// + /// Gets the new tier of SCP-127. + /// + public Scp127Tier Tier { get; } + + /// + public bool IsAllowed { get; set; } +} diff --git a/LabApi/Events/Arguments/Scp127Events/Scp127TalkedEventArgs.cs b/LabApi/Events/Arguments/Scp127Events/Scp127TalkedEventArgs.cs new file mode 100644 index 00000000..b3593573 --- /dev/null +++ b/LabApi/Events/Arguments/Scp127Events/Scp127TalkedEventArgs.cs @@ -0,0 +1,42 @@ +using InventorySystem.Items.Firearms; +using InventorySystem.Items.Firearms.Modules.Scp127; +using LabApi.Events.Arguments.Interfaces; +using LabApi.Features.Wrappers; +using System; +using static InventorySystem.Items.Firearms.Modules.Scp127.Scp127VoiceTriggerBase; + +namespace LabApi.Events.Arguments.Scp127Events; + +/// +/// Represents the arguments for the event. +/// +public class Scp127TalkedEventArgs : EventArgs, IScp127ItemEvent +{ + /// + /// Initializes a new instance of the class. + /// + /// The Scp-127 firearm. + /// The voiceline to be played. + /// The priority of the voiceline. + public Scp127TalkedEventArgs(Firearm weapon, Scp127VoiceLinesTranslation voiceLine, VoiceLinePriority priority) + { + Scp127Item = (Scp127Firearm)FirearmItem.Get(weapon); + VoiceLine = voiceLine; + Priority = priority; + } + + /// + /// Gets the SCP-127 firearm. + /// + public Scp127Firearm Scp127Item { get; } + + /// + /// Gets the voiceline the SCP-127 played. + /// + public Scp127VoiceLinesTranslation VoiceLine { get; } + + /// + /// Gets the priority the voiceline has been played with. + /// + public VoiceLinePriority Priority { get; } +} diff --git a/LabApi/Events/Arguments/Scp127Events/Scp127TalkingEventArgs.cs b/LabApi/Events/Arguments/Scp127Events/Scp127TalkingEventArgs.cs new file mode 100644 index 00000000..72500cf4 --- /dev/null +++ b/LabApi/Events/Arguments/Scp127Events/Scp127TalkingEventArgs.cs @@ -0,0 +1,46 @@ +using InventorySystem.Items.Firearms; +using InventorySystem.Items.Firearms.Modules.Scp127; +using LabApi.Events.Arguments.Interfaces; +using LabApi.Features.Wrappers; +using System; +using static InventorySystem.Items.Firearms.Modules.Scp127.Scp127VoiceTriggerBase; + +namespace LabApi.Events.Arguments.Scp127Events; + +/// +/// Represents the arguments for the event. +/// +public class Scp127TalkingEventArgs : EventArgs, IScp127ItemEvent, ICancellableEvent +{ + /// + /// Initializes a new instance of the class. + /// + /// The Scp-127 firearm. + /// The voiceline to be played. + /// The priority of the voiceline. + public Scp127TalkingEventArgs(Firearm weapon, Scp127VoiceLinesTranslation voiceLine, VoiceLinePriority priority) + { + Scp127Item = (Scp127Firearm)FirearmItem.Get(weapon); + VoiceLine = voiceLine; + Priority = priority; + IsAllowed = true; + } + + /// + /// Gets the SCP-127 firearm. + /// + public Scp127Firearm Scp127Item { get; } + + /// + /// Gets or sets the voiceline the SCP-127 will play. + /// + public Scp127VoiceLinesTranslation VoiceLine { get; set; } + + /// + /// Gets or sets the priority the voiceline will be played with. + /// + public VoiceLinePriority Priority { get; set; } + + /// + public bool IsAllowed { get; set; } +} diff --git a/LabApi/Events/Arguments/Scp173Events/Scp173AddedObserverEventArgs.cs b/LabApi/Events/Arguments/Scp173Events/Scp173AddedObserverEventArgs.cs index c81cf17b..0c2e8535 100644 --- a/LabApi/Events/Arguments/Scp173Events/Scp173AddedObserverEventArgs.cs +++ b/LabApi/Events/Arguments/Scp173Events/Scp173AddedObserverEventArgs.cs @@ -13,11 +13,11 @@ public class Scp173AddedObserverEventArgs : EventArgs, IPlayerEvent, ITargetEven /// Initializes a new instance of the class. /// /// The player that is observing the SCP-173 player. - /// The SCP-173 player instance. - public Scp173AddedObserverEventArgs(ReferenceHub target, ReferenceHub player) + /// The SCP-173 player instance. + public Scp173AddedObserverEventArgs(ReferenceHub target, ReferenceHub hub) { Target = Player.Get(target); - Player = Player.Get(player); + Player = Player.Get(hub); } /// diff --git a/LabApi/Events/Arguments/Scp173Events/Scp173AddingObserverEventArgs.cs b/LabApi/Events/Arguments/Scp173Events/Scp173AddingObserverEventArgs.cs index d1ab49b4..711b0ccb 100644 --- a/LabApi/Events/Arguments/Scp173Events/Scp173AddingObserverEventArgs.cs +++ b/LabApi/Events/Arguments/Scp173Events/Scp173AddingObserverEventArgs.cs @@ -13,12 +13,12 @@ public class Scp173AddingObserverEventArgs : EventArgs, IPlayerEvent, ITargetEve /// Initializes a new instance of the class. /// /// The player that is observing the SCP-173 player. - /// The SCP-173 player instance. - public Scp173AddingObserverEventArgs(ReferenceHub target, ReferenceHub player) + /// The SCP-173 player instance. + public Scp173AddingObserverEventArgs(ReferenceHub target, ReferenceHub hub) { IsAllowed = true; Target = Player.Get(target); - Player = Player.Get(player); + Player = Player.Get(hub); } /// diff --git a/LabApi/Events/Arguments/Scp173Events/Scp173BreakneckSpeedChangedEventArgs.cs b/LabApi/Events/Arguments/Scp173Events/Scp173BreakneckSpeedChangedEventArgs.cs index 1fde5556..8fdfcf00 100644 --- a/LabApi/Events/Arguments/Scp173Events/Scp173BreakneckSpeedChangedEventArgs.cs +++ b/LabApi/Events/Arguments/Scp173Events/Scp173BreakneckSpeedChangedEventArgs.cs @@ -12,11 +12,11 @@ public class Scp173BreakneckSpeedChangedEventArgs : EventArgs, IPlayerEvent /// /// Initializes a new instance of the class. /// - /// The SCP-173 player instance. + /// The SCP-173 player instance. /// The new breakneck speed state. - public Scp173BreakneckSpeedChangedEventArgs(ReferenceHub player, bool active) + public Scp173BreakneckSpeedChangedEventArgs(ReferenceHub hub, bool active) { - Player = Player.Get(player); + Player = Player.Get(hub); Active = active; } diff --git a/LabApi/Events/Arguments/Scp173Events/Scp173BreakneckSpeedChangingEventArgs.cs b/LabApi/Events/Arguments/Scp173Events/Scp173BreakneckSpeedChangingEventArgs.cs index 2d55a31d..f625325a 100644 --- a/LabApi/Events/Arguments/Scp173Events/Scp173BreakneckSpeedChangingEventArgs.cs +++ b/LabApi/Events/Arguments/Scp173Events/Scp173BreakneckSpeedChangingEventArgs.cs @@ -12,12 +12,12 @@ public class Scp173BreakneckSpeedChangingEventArgs : EventArgs, IPlayerEvent, IC /// /// Initializes a new instance of the class. /// - /// The SCP-173 player instance. + /// The SCP-173 player instance. /// The new breakneck speed state. - public Scp173BreakneckSpeedChangingEventArgs(ReferenceHub player, bool active) + public Scp173BreakneckSpeedChangingEventArgs(ReferenceHub hub, bool active) { IsAllowed = true; - Player = Player.Get(player); + Player = Player.Get(hub); Active = active; } @@ -27,7 +27,7 @@ public Scp173BreakneckSpeedChangingEventArgs(ReferenceHub player, bool active) public bool Active { get; } /// - /// The SCP-173 player instance. + /// The SCP-173 player instance. /// public Player Player { get; } diff --git a/LabApi/Events/Arguments/Scp173Events/Scp173CreatedTantrumEventArgs.cs b/LabApi/Events/Arguments/Scp173Events/Scp173CreatedTantrumEventArgs.cs index 96381655..b7e12947 100644 --- a/LabApi/Events/Arguments/Scp173Events/Scp173CreatedTantrumEventArgs.cs +++ b/LabApi/Events/Arguments/Scp173Events/Scp173CreatedTantrumEventArgs.cs @@ -14,11 +14,11 @@ public class Scp173CreatedTantrumEventArgs : EventArgs, IPlayerEvent, ITantrumEv /// Initializes a new instance of the class. /// /// The tantrum instance. - /// The SCP-173 player instance. - public Scp173CreatedTantrumEventArgs(TantrumEnvironmentalHazard tantrumInstance, ReferenceHub player) + /// The SCP-173 player instance. + public Scp173CreatedTantrumEventArgs(TantrumEnvironmentalHazard tantrumInstance, ReferenceHub hub) { Tantrum = TantrumHazard.Get(tantrumInstance); - Player = Player.Get(player); + Player = Player.Get(hub); } /// diff --git a/LabApi/Events/Arguments/Scp173Events/Scp173CreatingTantrumEventArgs.cs b/LabApi/Events/Arguments/Scp173Events/Scp173CreatingTantrumEventArgs.cs index 0fed36a0..e4d65fdb 100644 --- a/LabApi/Events/Arguments/Scp173Events/Scp173CreatingTantrumEventArgs.cs +++ b/LabApi/Events/Arguments/Scp173Events/Scp173CreatingTantrumEventArgs.cs @@ -12,11 +12,11 @@ public class Scp173CreatingTantrumEventArgs : EventArgs, IPlayerEvent, ICancella /// /// Initializes a new instance of the class. /// - /// The SCP-173 player instance. - public Scp173CreatingTantrumEventArgs(ReferenceHub player) + /// The SCP-173 player instance. + public Scp173CreatingTantrumEventArgs(ReferenceHub hub) { IsAllowed = true; - Player = Player.Get(player); + Player = Player.Get(hub); } /// diff --git a/LabApi/Events/Arguments/Scp173Events/Scp173PlayedSoundEventArgs.cs b/LabApi/Events/Arguments/Scp173Events/Scp173PlayedSoundEventArgs.cs index a53571f7..17dba443 100644 --- a/LabApi/Events/Arguments/Scp173Events/Scp173PlayedSoundEventArgs.cs +++ b/LabApi/Events/Arguments/Scp173Events/Scp173PlayedSoundEventArgs.cs @@ -13,11 +13,11 @@ public class Scp173PlayedSoundEventArgs : EventArgs, IPlayerEvent /// /// The sound id that is being played. /// - /// The SCP-173 player instance. - /// The sound id that is being played. - public Scp173PlayedSoundEventArgs(ReferenceHub player, Scp173AudioPlayer.Scp173SoundId soundId) + /// The SCP-173 player instance. + /// The sound id being played. + public Scp173PlayedSoundEventArgs(ReferenceHub hub, Scp173AudioPlayer.Scp173SoundId soundId) { - Player = Player.Get(player); + Player = Player.Get(hub); SoundId = soundId; } @@ -30,5 +30,4 @@ public Scp173PlayedSoundEventArgs(ReferenceHub player, Scp173AudioPlayer.Scp173S /// The SCP-173 player instance. /// public Player Player { get; } - } \ No newline at end of file diff --git a/LabApi/Events/Arguments/Scp173Events/Scp173PlayingSoundEventArgs.cs b/LabApi/Events/Arguments/Scp173Events/Scp173PlayingSoundEventArgs.cs index 2d704082..f1fc4f63 100644 --- a/LabApi/Events/Arguments/Scp173Events/Scp173PlayingSoundEventArgs.cs +++ b/LabApi/Events/Arguments/Scp173Events/Scp173PlayingSoundEventArgs.cs @@ -13,12 +13,12 @@ public class Scp173PlayingSoundEventArgs : EventArgs, IPlayerEvent, ICancellable /// /// The sound id that is going to be played. /// - /// The SCP-173 player instance. - /// The sound id that is going to be played. - public Scp173PlayingSoundEventArgs(ReferenceHub player, Scp173AudioPlayer.Scp173SoundId soundId) + /// The SCP-173 player instance. + /// The sound id going to be played. + public Scp173PlayingSoundEventArgs(ReferenceHub hub, Scp173AudioPlayer.Scp173SoundId soundId) { IsAllowed = true; - Player = Player.Get(player); + Player = Player.Get(hub); SoundId = soundId; } diff --git a/LabApi/Events/Arguments/Scp173Events/Scp173RemovedObserverEventArgs.cs b/LabApi/Events/Arguments/Scp173Events/Scp173RemovedObserverEventArgs.cs index 788e5264..5f51f5a4 100644 --- a/LabApi/Events/Arguments/Scp173Events/Scp173RemovedObserverEventArgs.cs +++ b/LabApi/Events/Arguments/Scp173Events/Scp173RemovedObserverEventArgs.cs @@ -13,11 +13,11 @@ public class Scp173RemovedObserverEventArgs : EventArgs, IPlayerEvent, ITargetEv /// Initializes a new instance of the class. /// /// The player that was observing the SCP-173 player. - /// The SCP-173 player instance. - public Scp173RemovedObserverEventArgs(ReferenceHub target, ReferenceHub player) + /// The SCP-173 player instance. + public Scp173RemovedObserverEventArgs(ReferenceHub target, ReferenceHub hub) { Target = Player.Get(target); - Player = Player.Get(player); + Player = Player.Get(hub); } /// diff --git a/LabApi/Events/Arguments/Scp173Events/Scp173RemovingObserverEventArgs.cs b/LabApi/Events/Arguments/Scp173Events/Scp173RemovingObserverEventArgs.cs index 31a08021..d3d1a19a 100644 --- a/LabApi/Events/Arguments/Scp173Events/Scp173RemovingObserverEventArgs.cs +++ b/LabApi/Events/Arguments/Scp173Events/Scp173RemovingObserverEventArgs.cs @@ -13,12 +13,12 @@ public class Scp173RemovingObserverEventArgs : EventArgs, IPlayerEvent, ITargetE /// Initializes a new instance of the class. /// /// The player that was observing the SCP-173 player. - /// The SCP-173 player instance. - public Scp173RemovingObserverEventArgs(ReferenceHub target, ReferenceHub player) + /// The SCP-173 player instance. + public Scp173RemovingObserverEventArgs(ReferenceHub target, ReferenceHub hub) { IsAllowed = true; Target = Player.Get(target); - Player = Player.Get(player); + Player = Player.Get(hub); } /// diff --git a/LabApi/Events/Arguments/Scp173Events/Scp173SnappedEventArgs.cs b/LabApi/Events/Arguments/Scp173Events/Scp173SnappedEventArgs.cs new file mode 100644 index 00000000..bc97f889 --- /dev/null +++ b/LabApi/Events/Arguments/Scp173Events/Scp173SnappedEventArgs.cs @@ -0,0 +1,32 @@ +using LabApi.Events.Arguments.Interfaces; +using LabApi.Features.Wrappers; +using System; + +namespace LabApi.Events.Arguments.Scp173Events; + +/// +/// Represents the arguments for the event. +/// +public class Scp173SnappedEventArgs : EventArgs, IPlayerEvent, ITargetEvent +{ + /// + /// Initializes a new instance of the class. + /// + /// The SCP-173 player. + /// The player that has been snapped. + public Scp173SnappedEventArgs(ReferenceHub hub, ReferenceHub target) + { + Player = Player.Get(hub); + Target = Player.Get(target); + } + + /// + /// Gets the SCP-173 player instance. + /// + public Player Player { get; } + + /// + /// Gets the player that has been snapped. + /// + public Player Target { get; } +} diff --git a/LabApi/Events/Arguments/Scp173Events/Scp173SnappingEventArgs.cs b/LabApi/Events/Arguments/Scp173Events/Scp173SnappingEventArgs.cs new file mode 100644 index 00000000..d05edee4 --- /dev/null +++ b/LabApi/Events/Arguments/Scp173Events/Scp173SnappingEventArgs.cs @@ -0,0 +1,38 @@ +using LabApi.Events.Arguments.Interfaces; +using LabApi.Features.Wrappers; +using System; + +namespace LabApi.Events.Arguments.Scp173Events; + +/// +/// Represents the arguments for the event. +/// +public class Scp173SnappingEventArgs : EventArgs, IPlayerEvent, ITargetEvent +{ + /// + /// Initializes a new instance of the class. + /// + /// The SCP-173 player. + /// The player to snap. + public Scp173SnappingEventArgs(ReferenceHub hub, ReferenceHub target) + { + IsAllowed = true; + Player = Player.Get(hub); + Target = Player.Get(target); + } + + /// + /// Gets the SCP-173 player instance. + /// + public Player Player { get; } + + /// + /// Gets or sets the player to snap. + /// + public Player Target { get; set; } + + /// + /// Gets or sets whether the SCP-173 player can snap the target. + /// + public bool IsAllowed { get; set; } +} diff --git a/LabApi/Events/Arguments/Scp173Events/Scp173TeleportedEventArgs.cs b/LabApi/Events/Arguments/Scp173Events/Scp173TeleportedEventArgs.cs new file mode 100644 index 00000000..e77a7e5b --- /dev/null +++ b/LabApi/Events/Arguments/Scp173Events/Scp173TeleportedEventArgs.cs @@ -0,0 +1,41 @@ +using LabApi.Events.Arguments.Interfaces; +using LabApi.Features.Wrappers; +using System; +using UnityEngine; + +namespace LabApi.Events.Arguments.Scp173Events; + +/// +/// Represents the arguments for the event. +/// +public class Scp173TeleportedEventArgs : EventArgs, IPlayerEvent +{ + /// + /// Initializes a new instance of the class. + /// + /// The SCP-173 player. + /// The target position to teleport to. + public Scp173TeleportedEventArgs(ReferenceHub hub, Vector3 position) + { + IsAllowed = true; + Player = Player.Get(hub); + Position = position; + } + + /// + /// Gets the SCP-173 player instance. + /// + public Player Player { get; } + + /// + /// Gets the target player position that the SCP-173 has teleported to. + /// Note that this position is on the floor and the has been teleported 1/2 of its character height up to prevent clipping through floor. + /// + public Vector3 Position { get; } + + /// + /// Gets or sets whether the SCP-173 player can teleport. + /// This even is fired even if the charge ability is not ready so you may override it on the server aswell. + /// + public bool IsAllowed { get; set; } +} diff --git a/LabApi/Events/Arguments/Scp173Events/Scp173TeleportingEventArgs.cs b/LabApi/Events/Arguments/Scp173Events/Scp173TeleportingEventArgs.cs new file mode 100644 index 00000000..461814b9 --- /dev/null +++ b/LabApi/Events/Arguments/Scp173Events/Scp173TeleportingEventArgs.cs @@ -0,0 +1,38 @@ +using LabApi.Events.Arguments.Interfaces; +using LabApi.Features.Wrappers; +using System; +using UnityEngine; + +namespace LabApi.Events.Arguments.Scp173Events; + +/// +/// Represents the arguments for the event. +/// +public class Scp173TeleportingEventArgs : EventArgs, IPlayerEvent, ICancellableEvent +{ + /// + /// Initializes a new instance of the class. + /// + /// The SCP-173 player. + /// The target position to teleport to. + public Scp173TeleportingEventArgs(ReferenceHub hub, Vector3 position) + { + Player = Player.Get(hub); + Position = position; + IsAllowed = true; + } + + /// + /// Gets the SCP-173 player instance. + /// + public Player Player { get; } + + /// + /// Gets or sets the target player position to teleport SCP-173 player to. + /// Note that this position is on the floor and the is then teleported 1/2 of its character height up to prevent clipping through floor. + /// + public Vector3 Position { get; set; } + + /// + public bool IsAllowed { get; set; } +} diff --git a/LabApi/Events/Arguments/Scp3114Events/Scp3114DisguisedEventArgs.cs b/LabApi/Events/Arguments/Scp3114Events/Scp3114DisguisedEventArgs.cs new file mode 100644 index 00000000..2efb3651 --- /dev/null +++ b/LabApi/Events/Arguments/Scp3114Events/Scp3114DisguisedEventArgs.cs @@ -0,0 +1,29 @@ +using LabApi.Events.Arguments.Interfaces; +using LabApi.Features.Wrappers; +using PlayerRoles.Ragdolls; +using System; + +namespace LabApi.Events.Arguments.Scp3114Events; + +/// +/// Represents the arguments for the event. +/// +public class Scp3114DisguisedEventArgs : EventArgs, IPlayerEvent, IRagdollEvent +{ + /// + /// Initializes a new instance of the class. + /// + /// The player SCP who disguised. + /// The ragdoll used for disguising purposes. + public Scp3114DisguisedEventArgs(ReferenceHub player, BasicRagdoll ragdoll) + { + Player = Player.Get(player); + Ragdoll = Ragdoll.Get(ragdoll); + } + + /// + public Player Player { get; } + + /// + public Ragdoll Ragdoll { get; } +} diff --git a/LabApi/Events/Arguments/Scp3114Events/Scp3114DisguisingEventArgs.cs b/LabApi/Events/Arguments/Scp3114Events/Scp3114DisguisingEventArgs.cs new file mode 100644 index 00000000..d5f2e7a5 --- /dev/null +++ b/LabApi/Events/Arguments/Scp3114Events/Scp3114DisguisingEventArgs.cs @@ -0,0 +1,33 @@ +using LabApi.Events.Arguments.Interfaces; +using LabApi.Features.Wrappers; +using PlayerRoles.Ragdolls; +using System; + +namespace LabApi.Events.Arguments.Scp3114Events; + +/// +/// Represents the arguments for the event. +/// +public class Scp3114DisguisingEventArgs : EventArgs, IPlayerEvent, IRagdollEvent, ICancellableEvent +{ + /// + /// Initializes a new instance of the class. + /// + /// The player SCP who is disguising. + /// The ragdoll used for disguising purposes. + public Scp3114DisguisingEventArgs(ReferenceHub player, BasicRagdoll ragdoll) + { + Player = Player.Get(player); + Ragdoll = Ragdoll.Get(ragdoll); + IsAllowed = true; + } + + /// + public Player Player { get; } + + /// + public Ragdoll Ragdoll { get; } + + /// + public bool IsAllowed { get; set; } +} diff --git a/LabApi/Events/Arguments/Scp3114Events/Scp3114RevealedEventArgs.cs b/LabApi/Events/Arguments/Scp3114Events/Scp3114RevealedEventArgs.cs new file mode 100644 index 00000000..8c17004d --- /dev/null +++ b/LabApi/Events/Arguments/Scp3114Events/Scp3114RevealedEventArgs.cs @@ -0,0 +1,30 @@ +using LabApi.Events.Arguments.Interfaces; +using LabApi.Features.Wrappers; +using System; + +namespace LabApi.Events.Arguments.Scp3114Events; + +/// +/// Represents the arguments for the event. +/// +public class Scp3114RevealedEventArgs : EventArgs, IPlayerEvent +{ + /// + /// Initializes a new instance of the class. + /// + /// The player SCP so is undisguised. + /// Bool whether the reveal is forced by timer running out or if it was player's request. + public Scp3114RevealedEventArgs(ReferenceHub player, bool forced) + { + Player = Player.Get(player); + Forced = forced; + } + + /// + public Player Player { get; } + + /// + /// Gets whether the reveal was forced by timer running out or if it was player's request. + /// + public bool Forced { get; } +} diff --git a/LabApi/Events/Arguments/Scp3114Events/Scp3114RevealingEventArgs.cs b/LabApi/Events/Arguments/Scp3114Events/Scp3114RevealingEventArgs.cs new file mode 100644 index 00000000..9bba6944 --- /dev/null +++ b/LabApi/Events/Arguments/Scp3114Events/Scp3114RevealingEventArgs.cs @@ -0,0 +1,34 @@ +using LabApi.Events.Arguments.Interfaces; +using LabApi.Features.Wrappers; +using System; + +namespace LabApi.Events.Arguments.Scp3114Events; + +/// +/// Represents the arguments for the event. +/// +public class Scp3114RevealingEventArgs : EventArgs, IPlayerEvent, ICancellableEvent +{ + /// + /// Initializes a new instance of the class. + /// + /// The player SCP who is undisguising. + /// Bool whether the reveal is forced by timer running out or if it was player's request. + public Scp3114RevealingEventArgs(ReferenceHub player, bool forced) + { + Player = Player.Get(player); + Forced = forced; + IsAllowed = true; + } + + /// + public Player Player { get; } + + /// + /// Gets whether the reveal is forced by timer running out or if it was player's request. + /// + public bool Forced { get; } + + /// + public bool IsAllowed { get; set; } +} diff --git a/LabApi/Events/Arguments/Scp3114Events/Scp3114StartedDanceEventArgs.cs b/LabApi/Events/Arguments/Scp3114Events/Scp3114StartedDanceEventArgs.cs new file mode 100644 index 00000000..431a4784 --- /dev/null +++ b/LabApi/Events/Arguments/Scp3114Events/Scp3114StartedDanceEventArgs.cs @@ -0,0 +1,30 @@ +using LabApi.Events.Arguments.Interfaces; +using LabApi.Features.Wrappers; +using System; + +namespace LabApi.Events.Arguments.Scp3114Events; + +/// +/// Represents the arguments for the event. +/// +public class Scp3114StartedDanceEventArgs : EventArgs, IPlayerEvent +{ + /// + /// Initializes a new instance of the class. + /// + /// The player who is starting to dance. + /// The index of the animation to play. + public Scp3114StartedDanceEventArgs(ReferenceHub player, byte danceId) + { + Player = Player.Get(player); + DanceId = danceId; + } + + /// + /// Gets or sets the index of the animation to play. + /// + public byte DanceId { get; } + + /// + public Player Player { get; } +} diff --git a/LabApi/Events/Arguments/Scp3114Events/Scp3114StartingDanceEventArgs.cs b/LabApi/Events/Arguments/Scp3114Events/Scp3114StartingDanceEventArgs.cs new file mode 100644 index 00000000..9f3a8099 --- /dev/null +++ b/LabApi/Events/Arguments/Scp3114Events/Scp3114StartingDanceEventArgs.cs @@ -0,0 +1,36 @@ +using LabApi.Events.Arguments.Interfaces; +using LabApi.Features.Wrappers; +using System; + +namespace LabApi.Events.Arguments.Scp3114Events; + +/// +/// Represents the arguments for the event. +/// +public class Scp3114StartingDanceEventArgs : EventArgs, IPlayerEvent, ICancellableEvent +{ + /// + /// Initializes a new instance of the class. + /// + /// The player who is starting to dance. + /// The index of the animation to play. + public Scp3114StartingDanceEventArgs(ReferenceHub player, byte danceId) + { + Player = Player.Get(player); + DanceId = danceId; + IsAllowed = true; + } + + /// + public Player Player { get; } + + /// + /// Gets or sets the index of the animation to play. + /// Currently there are 7 dance variants in game. + /// Any value above max length will be moved to equal index via modulo (%) operator. + /// + public byte DanceId { get; set; } + + /// + public bool IsAllowed { get; set; } +} diff --git a/LabApi/Events/Arguments/Scp3114Events/Scp3114StrangleAbortedEventArgs.cs b/LabApi/Events/Arguments/Scp3114Events/Scp3114StrangleAbortedEventArgs.cs new file mode 100644 index 00000000..fbd89912 --- /dev/null +++ b/LabApi/Events/Arguments/Scp3114Events/Scp3114StrangleAbortedEventArgs.cs @@ -0,0 +1,32 @@ +using LabApi.Events.Arguments.Interfaces; +using LabApi.Features.Wrappers; +using System; + +namespace LabApi.Events.Arguments.Scp3114Events; + +/// +/// Represents the arguments for the events. +/// +public class Scp3114StrangleAbortedEventArgs : EventArgs, IPlayerEvent, ITargetEvent +{ + /// + /// Initializes a new instance of the class. + /// + /// The component of the SCP-3114 player. + /// The component of the target player. + public Scp3114StrangleAbortedEventArgs(ReferenceHub scp3114Hub, ReferenceHub targetHub) + { + Player = Player.Get(scp3114Hub); + Target = Player.Get(targetHub); + } + + /// + /// The SCP-3114 player. + /// + public Player Player { get; } + + /// + /// The strangle target. + /// + public Player Target { get; } +} diff --git a/LabApi/Events/Arguments/Scp3114Events/Scp3114StrangleAbortingEventArgs.cs b/LabApi/Events/Arguments/Scp3114Events/Scp3114StrangleAbortingEventArgs.cs new file mode 100644 index 00000000..b1543bbf --- /dev/null +++ b/LabApi/Events/Arguments/Scp3114Events/Scp3114StrangleAbortingEventArgs.cs @@ -0,0 +1,36 @@ +using LabApi.Events.Arguments.Interfaces; +using LabApi.Features.Wrappers; +using System; + +namespace LabApi.Events.Arguments.Scp3114Events; + +/// +/// Represents the arguments for the events. +/// +public class Scp3114StrangleAbortingEventArgs : EventArgs, IPlayerEvent, ITargetEvent, ICancellableEvent +{ + /// + /// Initializes a new instance of the class. + /// + /// The component of the SCP-3114 player. + /// The component of the target player. + public Scp3114StrangleAbortingEventArgs(ReferenceHub scp3114Hub, ReferenceHub targetHub) + { + Player = Player.Get(scp3114Hub); + Target = Player.Get(targetHub); + IsAllowed = true; + } + + /// + /// The SCP-3114 player. + /// + public Player Player { get; } + + /// + /// The strangle target. + /// + public Player Target { get; } + + /// + public bool IsAllowed { get; set; } +} diff --git a/LabApi/Events/Arguments/Scp3114Events/Scp3114StrangleStartedEventArgs.cs b/LabApi/Events/Arguments/Scp3114Events/Scp3114StrangleStartedEventArgs.cs new file mode 100644 index 00000000..b784b4a6 --- /dev/null +++ b/LabApi/Events/Arguments/Scp3114Events/Scp3114StrangleStartedEventArgs.cs @@ -0,0 +1,32 @@ +using LabApi.Events.Arguments.Interfaces; +using LabApi.Features.Wrappers; +using System; + +namespace LabApi.Events.Arguments.Scp3114Events; + +/// +/// Represents the arguments for the events. +/// +public class Scp3114StrangleStartedEventArgs : EventArgs, IPlayerEvent, ITargetEvent +{ + /// + /// Initializes a new instance of the class. + /// + /// The component of the SCP-3114 player. + /// The component of the target player. + public Scp3114StrangleStartedEventArgs(ReferenceHub scp3114Hub, ReferenceHub targetHub) + { + Player = Player.Get(scp3114Hub); + Target = Player.Get(targetHub); + } + + /// + /// The SCP-3114 player. + /// + public Player Player { get; } + + /// + /// The strangle target. + /// + public Player Target { get; } +} diff --git a/LabApi/Events/Arguments/Scp3114Events/Scp3114StrangleStartingEventArgs.cs b/LabApi/Events/Arguments/Scp3114Events/Scp3114StrangleStartingEventArgs.cs new file mode 100644 index 00000000..96193a0c --- /dev/null +++ b/LabApi/Events/Arguments/Scp3114Events/Scp3114StrangleStartingEventArgs.cs @@ -0,0 +1,36 @@ +using LabApi.Events.Arguments.Interfaces; +using LabApi.Features.Wrappers; +using System; + +namespace LabApi.Events.Arguments.Scp3114Events; + +/// +/// Represents the arguments for the events. +/// +public class Scp3114StrangleStartingEventArgs : EventArgs, IPlayerEvent, ITargetEvent, ICancellableEvent +{ + /// + /// Initializes a new instance of the class. + /// + /// The component of the SCP-3114 player. + /// The component of the target player. + public Scp3114StrangleStartingEventArgs(ReferenceHub scp3114Hub, ReferenceHub targetHub) + { + Player = Player.Get(scp3114Hub); + Target = Player.Get(targetHub); + IsAllowed = true; + } + + /// + /// The SCP-3114 player. + /// + public Player Player { get; } + + /// + /// The strangle target. + /// + public Player Target { get; } + + /// + public bool IsAllowed { get; set; } +} diff --git a/LabApi/Events/Arguments/Scp914Events/Scp914ActivatedEventArgs.cs b/LabApi/Events/Arguments/Scp914Events/Scp914ActivatedEventArgs.cs index a740f898..60df6840 100644 --- a/LabApi/Events/Arguments/Scp914Events/Scp914ActivatedEventArgs.cs +++ b/LabApi/Events/Arguments/Scp914Events/Scp914ActivatedEventArgs.cs @@ -14,11 +14,11 @@ public class Scp914ActivatedEventArgs : EventArgs, IScp914Event, IPlayerEvent /// Initializes a new instance of the class. /// /// The knob setting of SCP-914. - /// The player that activated SCP-914. - public Scp914ActivatedEventArgs(Scp914KnobSetting knobSetting, ReferenceHub player) + /// The player that activated SCP-914. + public Scp914ActivatedEventArgs(Scp914KnobSetting knobSetting, ReferenceHub hub) { KnobSetting = knobSetting; - Player = Player.Get(player); + Player = Player.Get(hub); } /// diff --git a/LabApi/Events/Arguments/Scp914Events/Scp914ActivatingEventArgs.cs b/LabApi/Events/Arguments/Scp914Events/Scp914ActivatingEventArgs.cs index 67edee0c..1b4f5973 100644 --- a/LabApi/Events/Arguments/Scp914Events/Scp914ActivatingEventArgs.cs +++ b/LabApi/Events/Arguments/Scp914Events/Scp914ActivatingEventArgs.cs @@ -14,12 +14,12 @@ public class Scp914ActivatingEventArgs : EventArgs, IScp914Event, IPlayerEvent, /// Initializes a new instance of the class. /// /// The knob setting of SCP-914. - /// The player that is activating SCP-914. - public Scp914ActivatingEventArgs(Scp914KnobSetting knobSetting, ReferenceHub player) + /// The player that is activating SCP-914. + public Scp914ActivatingEventArgs(Scp914KnobSetting knobSetting, ReferenceHub hub) { IsAllowed = true; KnobSetting = knobSetting; - Player = Player.Get(player); + Player = Player.Get(hub); } /// diff --git a/LabApi/Events/Arguments/Scp914Events/Scp914KnobChangedEventArgs.cs b/LabApi/Events/Arguments/Scp914Events/Scp914KnobChangedEventArgs.cs index bcb0f4f9..e9ccec50 100644 --- a/LabApi/Events/Arguments/Scp914Events/Scp914KnobChangedEventArgs.cs +++ b/LabApi/Events/Arguments/Scp914Events/Scp914KnobChangedEventArgs.cs @@ -15,12 +15,12 @@ public class Scp914KnobChangedEventArgs : EventArgs, IScp914Event, IPlayerEvent /// /// The old knob setting of SCP-914. /// The new knob setting of SCP-914. - /// The player that has changed the knob. - public Scp914KnobChangedEventArgs(Scp914KnobSetting oldKnobSetting, Scp914KnobSetting knobSetting, ReferenceHub player) + /// The player that has changed the knob. + public Scp914KnobChangedEventArgs(Scp914KnobSetting oldKnobSetting, Scp914KnobSetting knobSetting, ReferenceHub hub) { OldKnobSetting = oldKnobSetting; KnobSetting = knobSetting; - Player = Player.Get(player); + Player = Player.Get(hub); } /// diff --git a/LabApi/Events/Arguments/Scp914Events/Scp914KnobChangingEventArgs.cs b/LabApi/Events/Arguments/Scp914Events/Scp914KnobChangingEventArgs.cs index 371740aa..fe89d86a 100644 --- a/LabApi/Events/Arguments/Scp914Events/Scp914KnobChangingEventArgs.cs +++ b/LabApi/Events/Arguments/Scp914Events/Scp914KnobChangingEventArgs.cs @@ -15,13 +15,13 @@ public class Scp914KnobChangingEventArgs : EventArgs, IScp914Event, IPlayerEvent /// /// The old knob setting of SCP-914. /// The new knob setting of SCP-914. - /// The player that is changing the knob. - public Scp914KnobChangingEventArgs(Scp914KnobSetting oldKnobSetting, Scp914KnobSetting knobSetting, ReferenceHub player) + /// The player that is changing the knob. + public Scp914KnobChangingEventArgs(Scp914KnobSetting oldKnobSetting, Scp914KnobSetting knobSetting, ReferenceHub hub) { IsAllowed = true; OldKnobSetting = oldKnobSetting; KnobSetting = knobSetting; - Player = Player.Get(player); + Player = Player.Get(hub); } /// diff --git a/LabApi/Events/Arguments/Scp914Events/Scp914ProcessedInventoryItemEventArgs.cs b/LabApi/Events/Arguments/Scp914Events/Scp914ProcessedInventoryItemEventArgs.cs index ceddecfe..a6842c98 100644 --- a/LabApi/Events/Arguments/Scp914Events/Scp914ProcessedInventoryItemEventArgs.cs +++ b/LabApi/Events/Arguments/Scp914Events/Scp914ProcessedInventoryItemEventArgs.cs @@ -1,8 +1,8 @@ +using InventorySystem.Items; using LabApi.Events.Arguments.Interfaces; using LabApi.Features.Wrappers; using Scp914; using System; -using InventorySystem.Items; namespace LabApi.Events.Arguments.Scp914Events; @@ -17,13 +17,13 @@ public class Scp914ProcessedInventoryItemEventArgs : EventArgs, IScp914Event, II /// The old item type. /// The new item that has been processed by SCP-914. /// The knob setting of SCP-914. - /// The owner of the item. - public Scp914ProcessedInventoryItemEventArgs(ItemType oldItemType, ItemBase item, Scp914KnobSetting knobSetting, ReferenceHub player) + /// The owner of the item. + public Scp914ProcessedInventoryItemEventArgs(ItemType oldItemType, ItemBase item, Scp914KnobSetting knobSetting, ReferenceHub hub) { OldItemType = oldItemType; Item = Item.Get(item); KnobSetting = knobSetting; - Player = Player.Get(player); + Player = Player.Get(hub); } /// diff --git a/LabApi/Events/Arguments/Scp914Events/Scp914ProcessedPickupEventArgs.cs b/LabApi/Events/Arguments/Scp914Events/Scp914ProcessedPickupEventArgs.cs index 441cc636..d8cd03d1 100644 --- a/LabApi/Events/Arguments/Scp914Events/Scp914ProcessedPickupEventArgs.cs +++ b/LabApi/Events/Arguments/Scp914Events/Scp914ProcessedPickupEventArgs.cs @@ -1,8 +1,8 @@ -using System; using InventorySystem.Items.Pickups; using LabApi.Events.Arguments.Interfaces; using LabApi.Features.Wrappers; using Scp914; +using System; using UnityEngine; namespace LabApi.Events.Arguments.Scp914Events; diff --git a/LabApi/Events/Arguments/Scp914Events/Scp914ProcessedPlayerEventArgs.cs b/LabApi/Events/Arguments/Scp914Events/Scp914ProcessedPlayerEventArgs.cs index a982ef84..d7915df9 100644 --- a/LabApi/Events/Arguments/Scp914Events/Scp914ProcessedPlayerEventArgs.cs +++ b/LabApi/Events/Arguments/Scp914Events/Scp914ProcessedPlayerEventArgs.cs @@ -16,12 +16,12 @@ public class Scp914ProcessedPlayerEventArgs : EventArgs, IScp914Event, IPlayerEv /// /// The knob setting of SCP-914. /// The new position that the player has been processed into. - /// The player that has been processed by SCP-914. - public Scp914ProcessedPlayerEventArgs(Vector3 newPosition, Scp914KnobSetting knobSetting, ReferenceHub player) + /// The player that has been processed by SCP-914. + public Scp914ProcessedPlayerEventArgs(Vector3 newPosition, Scp914KnobSetting knobSetting, ReferenceHub hub) { NewPosition = newPosition; KnobSetting = knobSetting; - Player = Player.Get(player); + Player = Player.Get(hub); } /// diff --git a/LabApi/Events/Arguments/Scp914Events/Scp914ProcessingInventoryItemEventArgs.cs b/LabApi/Events/Arguments/Scp914Events/Scp914ProcessingInventoryItemEventArgs.cs index 6e3dd7fd..761429f2 100644 --- a/LabApi/Events/Arguments/Scp914Events/Scp914ProcessingInventoryItemEventArgs.cs +++ b/LabApi/Events/Arguments/Scp914Events/Scp914ProcessingInventoryItemEventArgs.cs @@ -1,7 +1,7 @@ +using InventorySystem.Items; using LabApi.Events.Arguments.Interfaces; using LabApi.Features.Wrappers; using Scp914; -using InventorySystem.Items; using System; namespace LabApi.Events.Arguments.Scp914Events; @@ -16,13 +16,13 @@ public class Scp914ProcessingInventoryItemEventArgs : EventArgs, IScp914Event, I /// /// The item that is being processed by SCP-914. /// The knob setting of SCP-914. - /// The owner of the item. - public Scp914ProcessingInventoryItemEventArgs(ItemBase item, Scp914KnobSetting knobSetting, ReferenceHub player) + /// The owner of the item. + public Scp914ProcessingInventoryItemEventArgs(ItemBase item, Scp914KnobSetting knobSetting, ReferenceHub hub) { IsAllowed = true; Item = Item.Get(item); KnobSetting = knobSetting; - Player = Player.Get(player); + Player = Player.Get(hub); } /// diff --git a/LabApi/Events/Arguments/Scp914Events/Scp914ProcessingPickupEventArgs.cs b/LabApi/Events/Arguments/Scp914Events/Scp914ProcessingPickupEventArgs.cs index 05cdf2b1..0939f9d5 100644 --- a/LabApi/Events/Arguments/Scp914Events/Scp914ProcessingPickupEventArgs.cs +++ b/LabApi/Events/Arguments/Scp914Events/Scp914ProcessingPickupEventArgs.cs @@ -1,9 +1,9 @@ -using System; +using InventorySystem.Items.Pickups; using LabApi.Events.Arguments.Interfaces; using LabApi.Features.Wrappers; using Scp914; +using System; using UnityEngine; -using InventorySystem.Items.Pickups; namespace LabApi.Events.Arguments.Scp914Events; diff --git a/LabApi/Events/Arguments/Scp914Events/Scp914ProcessingPlayerEventArgs.cs b/LabApi/Events/Arguments/Scp914Events/Scp914ProcessingPlayerEventArgs.cs index 8887d521..8920020f 100644 --- a/LabApi/Events/Arguments/Scp914Events/Scp914ProcessingPlayerEventArgs.cs +++ b/LabApi/Events/Arguments/Scp914Events/Scp914ProcessingPlayerEventArgs.cs @@ -16,13 +16,13 @@ public class Scp914ProcessingPlayerEventArgs : EventArgs, IScp914Event, IPlayerE /// /// The new position that the player will be processed into. /// The knob setting of SCP-914. - /// The player that is being processed by SCP-914. - public Scp914ProcessingPlayerEventArgs(Vector3 newPosition, Scp914KnobSetting knobSetting, ReferenceHub player) + /// The player that is being processed by SCP-914. + public Scp914ProcessingPlayerEventArgs(Vector3 newPosition, Scp914KnobSetting knobSetting, ReferenceHub hub) { IsAllowed = true; NewPosition = newPosition; KnobSetting = knobSetting; - Player = Player.Get(player); + Player = Player.Get(hub); } /// diff --git a/LabApi/Events/Arguments/Scp939Events/Scp939AttackedEventArgs.cs b/LabApi/Events/Arguments/Scp939Events/Scp939AttackedEventArgs.cs index 530a0efa..570d8226 100644 --- a/LabApi/Events/Arguments/Scp939Events/Scp939AttackedEventArgs.cs +++ b/LabApi/Events/Arguments/Scp939Events/Scp939AttackedEventArgs.cs @@ -12,12 +12,12 @@ public class Scp939AttackedEventArgs : EventArgs, IPlayerEvent, ITargetEvent /// /// Initializes a new instance of the class. /// - /// The SCP-939 player instance. + /// The SCP-939 player instance. /// The destructible that was attacked. /// The damage dealt. - public Scp939AttackedEventArgs(ReferenceHub player, ReferenceHub target, float damage) + public Scp939AttackedEventArgs(ReferenceHub hub, ReferenceHub target, float damage) { - Player = Player.Get(player); + Player = Player.Get(hub); Target = Player.Get(target); Damage = damage; } diff --git a/LabApi/Events/Arguments/Scp939Events/Scp939AttackingEventArgs.cs b/LabApi/Events/Arguments/Scp939Events/Scp939AttackingEventArgs.cs index 847686da..fe9692b9 100644 --- a/LabApi/Events/Arguments/Scp939Events/Scp939AttackingEventArgs.cs +++ b/LabApi/Events/Arguments/Scp939Events/Scp939AttackingEventArgs.cs @@ -12,13 +12,13 @@ public class Scp939AttackingEventArgs : EventArgs, IPlayerEvent, ITargetEvent, I /// /// Initializes a new instance of the class. /// - /// The SCP-939 player instance. + /// The SCP-939 player instance. /// The destructible that is being attacked. /// The damage dealt. - public Scp939AttackingEventArgs(ReferenceHub player, ReferenceHub target, float damage) + public Scp939AttackingEventArgs(ReferenceHub hub, ReferenceHub target, float damage) { IsAllowed = true; - Player = Player.Get(player); + Player = Player.Get(hub); Target = Player.Get(target); Damage = damage; } diff --git a/LabApi/Events/Arguments/Scp939Events/Scp939CreatedAmnesticCloudEventArgs.cs b/LabApi/Events/Arguments/Scp939Events/Scp939CreatedAmnesticCloudEventArgs.cs index e3d03225..5fbd6700 100644 --- a/LabApi/Events/Arguments/Scp939Events/Scp939CreatedAmnesticCloudEventArgs.cs +++ b/LabApi/Events/Arguments/Scp939Events/Scp939CreatedAmnesticCloudEventArgs.cs @@ -13,11 +13,11 @@ public class Scp939CreatedAmnesticCloudEventArgs : EventArgs, IPlayerEvent, IAmn /// /// Initializes a new instance of the class. /// - /// The SCP-939 player instance. + /// The SCP-939 player instance. /// The created amnestic cloud instance. - public Scp939CreatedAmnesticCloudEventArgs(ReferenceHub player, Scp939AmnesticCloudInstance amnesticCloudInstance) + public Scp939CreatedAmnesticCloudEventArgs(ReferenceHub hub, Scp939AmnesticCloudInstance amnesticCloudInstance) { - Player = Player.Get(player); + Player = Player.Get(hub); AmnesticCloud = AmnesticCloudHazard.Get(amnesticCloudInstance); } diff --git a/LabApi/Events/Arguments/Scp939Events/Scp939CreatingAmnesticCloudEventArgs.cs b/LabApi/Events/Arguments/Scp939Events/Scp939CreatingAmnesticCloudEventArgs.cs index 3b11555a..823b3af6 100644 --- a/LabApi/Events/Arguments/Scp939Events/Scp939CreatingAmnesticCloudEventArgs.cs +++ b/LabApi/Events/Arguments/Scp939Events/Scp939CreatingAmnesticCloudEventArgs.cs @@ -12,11 +12,11 @@ public class Scp939CreatingAmnesticCloudEventArgs : EventArgs, IPlayerEvent, ICa /// /// Initializes a new instance of the class. /// - /// The SCP-939 player instance. - public Scp939CreatingAmnesticCloudEventArgs(ReferenceHub player) + /// The SCP-939 player instance. + public Scp939CreatingAmnesticCloudEventArgs(ReferenceHub hub) { IsAllowed = true; - Player = Player.Get(player); + Player = Player.Get(hub); } /// diff --git a/LabApi/Events/Arguments/Scp939Events/Scp939FocusedEventArgs.cs b/LabApi/Events/Arguments/Scp939Events/Scp939FocusedEventArgs.cs new file mode 100644 index 00000000..67400b06 --- /dev/null +++ b/LabApi/Events/Arguments/Scp939Events/Scp939FocusedEventArgs.cs @@ -0,0 +1,32 @@ +using LabApi.Events.Arguments.Interfaces; +using LabApi.Features.Wrappers; +using System; + +namespace LabApi.Events.Arguments.Scp939Events; + +/// +/// Represents the event arguments for when SCP-939 has focused. +/// +public class Scp939FocusedEventArgs : EventArgs, IPlayerEvent +{ + /// + /// Initializes a new instance of the class. + /// + /// The SCP-939 player instance. + /// A value indicating whether SCP-939 is in the focus state. + public Scp939FocusedEventArgs(ReferenceHub hub, bool focusState) + { + Player = Player.Get(hub); + FocusState = focusState; + } + + /// + /// Gets the 939 player instance. + /// + public Player Player { get; } + + /// + /// Gets the current state of the SCP-939 focus ability. + /// + public bool FocusState { get; } +} \ No newline at end of file diff --git a/LabApi/Events/Arguments/Scp939Events/Scp939LungedEventArgs.cs b/LabApi/Events/Arguments/Scp939Events/Scp939LungedEventArgs.cs index 971aac77..e22cf2f3 100644 --- a/LabApi/Events/Arguments/Scp939Events/Scp939LungedEventArgs.cs +++ b/LabApi/Events/Arguments/Scp939Events/Scp939LungedEventArgs.cs @@ -13,11 +13,11 @@ public class Scp939LungedEventArgs : EventArgs, IPlayerEvent /// /// Initializes a new instance of the class. /// - /// The SCP-939 player instance. + /// The SCP-939 player instance. /// The SCP-939 lunge state. - public Scp939LungedEventArgs(ReferenceHub player, Scp939LungeState lungeState) + public Scp939LungedEventArgs(ReferenceHub hub, Scp939LungeState lungeState) { - Player = Player.Get(player); + Player = Player.Get(hub); LungeState = lungeState; } diff --git a/LabApi/Events/Arguments/Scp939Events/Scp939LungingEventArgs.cs b/LabApi/Events/Arguments/Scp939Events/Scp939LungingEventArgs.cs index d10c4759..d5e2678c 100644 --- a/LabApi/Events/Arguments/Scp939Events/Scp939LungingEventArgs.cs +++ b/LabApi/Events/Arguments/Scp939Events/Scp939LungingEventArgs.cs @@ -13,12 +13,12 @@ public class Scp939LungingEventArgs : EventArgs, ICancellableEvent, IPlayerEvent /// /// Initializes a new instance of the class. /// - /// The SCP-939 player instance. + /// The SCP-939 player instance. /// The SCP-939 lunge state. - public Scp939LungingEventArgs(ReferenceHub player, Scp939LungeState lungeState) + public Scp939LungingEventArgs(ReferenceHub hub, Scp939LungeState lungeState) { IsAllowed = true; - Player = Player.Get(player); + Player = Player.Get(hub); LungeState = lungeState; } diff --git a/LabApi/Events/Arguments/Scp939Events/Scp939MimickedEnvironmentEventArgs.cs b/LabApi/Events/Arguments/Scp939Events/Scp939MimickedEnvironmentEventArgs.cs new file mode 100644 index 00000000..cb49c1e2 --- /dev/null +++ b/LabApi/Events/Arguments/Scp939Events/Scp939MimickedEnvironmentEventArgs.cs @@ -0,0 +1,32 @@ +using LabApi.Events.Arguments.Interfaces; +using LabApi.Features.Wrappers; +using System; + +namespace LabApi.Events.Arguments.Scp939Events; + +/// +/// Represents the event arguments for when SCP-939 has mimicked the environment. +/// +public class Scp939MimickedEnvironmentEventArgs : EventArgs, IPlayerEvent +{ + /// + /// Initializes a new instance of the class. + /// + /// The SCP-939 player instance. + /// The played environmental sequence. + public Scp939MimickedEnvironmentEventArgs(ReferenceHub hub, byte playedSequence) + { + Player = Player.Get(hub); + PlayedSequence = playedSequence; + } + + /// + /// Gets the 939 player instance. + /// + public Player Player { get; } + + /// + /// Gets the played environmental sequence. + /// + public byte PlayedSequence { get; } +} \ No newline at end of file diff --git a/LabApi/Events/Arguments/Scp939Events/Scp939MimickingEnvironmentEventArgs.cs b/LabApi/Events/Arguments/Scp939Events/Scp939MimickingEnvironmentEventArgs.cs new file mode 100644 index 00000000..c2381769 --- /dev/null +++ b/LabApi/Events/Arguments/Scp939Events/Scp939MimickingEnvironmentEventArgs.cs @@ -0,0 +1,44 @@ +using LabApi.Events.Arguments.Interfaces; +using LabApi.Features.Wrappers; +using System; + +namespace LabApi.Events.Arguments.Scp939Events; + +/// +/// Represents the event arguments for when SCP-939 is mimicking the environment. +/// +public class Scp939MimickingEnvironmentEventArgs : EventArgs, IPlayerEvent, ICancellableEvent +{ + /// + /// Initializes a new instance of the class. + /// + /// The SCP-939 player instance. + /// The selected environmental sequence to play. + /// The cooldown for mimicking the environment. + public Scp939MimickingEnvironmentEventArgs(ReferenceHub hub, byte selectedSequence, float cooldownTime) + { + Player = Player.Get(hub); + SelectedSequence = selectedSequence; + CooldownTime = cooldownTime; + + IsAllowed = true; + } + + /// + /// Gets the 939 player instance. + /// + public Player Player { get; } + + /// + /// Gets or sets the selected sequence to play. + /// + public byte SelectedSequence { get; set; } + + /// + /// Gets or sets the cooldown for mimicking the environment. + /// + public float CooldownTime { get; set; } + + /// + public bool IsAllowed { get; set; } +} \ No newline at end of file diff --git a/LabApi/Events/Arguments/ScpEvents/ScpHumeShieldBrokenEventArgs.cs b/LabApi/Events/Arguments/ScpEvents/ScpHumeShieldBrokenEventArgs.cs new file mode 100644 index 00000000..0c3f14de --- /dev/null +++ b/LabApi/Events/Arguments/ScpEvents/ScpHumeShieldBrokenEventArgs.cs @@ -0,0 +1,23 @@ +using LabApi.Events.Arguments.Interfaces; +using LabApi.Features.Wrappers; +using System; + +namespace LabApi.Events.Arguments.ScpEvents; + +/// +/// Represents the arguments for the event. +/// +public class ScpHumeShieldBrokenEventArgs : EventArgs, IPlayerEvent +{ + /// + /// Initializes a new instance of the class. + /// + /// The player SCP whom hume shield broke. + public ScpHumeShieldBrokenEventArgs(ReferenceHub player) + { + Player = Player.Get(player); + } + + /// + public Player Player { get; } +} \ No newline at end of file diff --git a/LabApi/Events/Arguments/ServerEvents/AchievedMilestoneEventArgs.cs b/LabApi/Events/Arguments/ServerEvents/AchievedMilestoneEventArgs.cs new file mode 100644 index 00000000..1dd99dd7 --- /dev/null +++ b/LabApi/Events/Arguments/ServerEvents/AchievedMilestoneEventArgs.cs @@ -0,0 +1,38 @@ +using PlayerRoles; +using System; + +namespace LabApi.Events.Arguments.ServerEvents; + +/// +/// Represents the arguments for the event. +/// +public class AchievedMilestoneEventArgs : EventArgs +{ + /// + /// Initializes a new instance of the class. + /// + /// The faction that achieved this milestone. + /// The influence threshold for this milestone. + /// The index of the achieved milestone. + public AchievedMilestoneEventArgs(Faction faction, int threshold, int milestoneIndex) + { + Faction = faction; + Threshold = threshold; + MilestoneIndex = milestoneIndex; + } + + /// + /// Gets the faction that achieved this milestone. + /// + public Faction Faction { get; } + + /// + /// Gets the influence threshold for this milestone. + /// + public int Threshold { get; } + + /// + /// Gets the index of the achieved milestone. + /// + public int MilestoneIndex { get; } +} \ No newline at end of file diff --git a/LabApi/Events/Arguments/ServerEvents/AchievingMilestoneEventArgs.cs b/LabApi/Events/Arguments/ServerEvents/AchievingMilestoneEventArgs.cs new file mode 100644 index 00000000..3a9992ee --- /dev/null +++ b/LabApi/Events/Arguments/ServerEvents/AchievingMilestoneEventArgs.cs @@ -0,0 +1,44 @@ +using LabApi.Events.Arguments.Interfaces; +using PlayerRoles; +using System; + +namespace LabApi.Events.Arguments.ServerEvents; + +/// +/// Represents the arguments for the event. +/// +public class AchievingMilestoneEventArgs : EventArgs, ICancellableEvent +{ + /// + /// Initializes a new instance of the class. + /// + /// The faction that achieved this milestone. + /// The influence threshold for this milestone. + /// The index of the achieved milestone. + public AchievingMilestoneEventArgs(Faction faction, int threshold, int milestoneIndex) + { + Faction = faction; + Threshold = threshold; + MilestoneIndex = milestoneIndex; + + IsAllowed = true; + } + + /// + /// Gets the faction that achieved this milestone. + /// + public Faction Faction { get; } + + /// + /// Gets the influence threshold for this milestone. + /// + public int Threshold { get; } + + /// + /// Gets the index of the achieved milestone. + /// + public int MilestoneIndex { get; } + + /// + public bool IsAllowed { get; set; } +} \ No newline at end of file diff --git a/LabApi/Events/Arguments/ServerEvents/BlastDoorChangedEventArgs.cs b/LabApi/Events/Arguments/ServerEvents/BlastDoorChangedEventArgs.cs new file mode 100644 index 00000000..9038df7d --- /dev/null +++ b/LabApi/Events/Arguments/ServerEvents/BlastDoorChangedEventArgs.cs @@ -0,0 +1,30 @@ +using System; + +namespace LabApi.Events.Arguments.ServerEvents; + +/// +/// Represents the arguments for the event. +/// +public class BlastDoorChangedEventArgs : EventArgs +{ + /// + /// Initializes a new instance of the class. + /// + /// The door that is chaning it's state. + /// The 's new state. + public BlastDoorChangedEventArgs(BlastDoor blastDoor, bool newState) + { + BlastDoor = blastDoor; + NewState = newState; + } + + /// + /// Gets the current Blast Door. + /// + public BlastDoor BlastDoor { get; } + + /// + /// Gets the new state. + /// + public bool NewState { get; } +} diff --git a/LabApi/Events/Arguments/ServerEvents/BlastDoorChangingEventArgs.cs b/LabApi/Events/Arguments/ServerEvents/BlastDoorChangingEventArgs.cs new file mode 100644 index 00000000..bd0e8f86 --- /dev/null +++ b/LabApi/Events/Arguments/ServerEvents/BlastDoorChangingEventArgs.cs @@ -0,0 +1,36 @@ +using LabApi.Events.Arguments.Interfaces; +using System; + +namespace LabApi.Events.Arguments.ServerEvents; + +/// +/// Represents the arguments for the event. +/// +public class BlastDoorChangingEventArgs : EventArgs, ICancellableEvent +{ + /// + /// Initializes a new instance of the class. + /// + /// The door that is changing it's state. + /// The 's new state. + public BlastDoorChangingEventArgs(BlastDoor blastDoor, bool newState) + { + BlastDoor = blastDoor; + NewState = newState; + + IsAllowed = true; + } + + /// + /// Gets the current Blast Door. + /// + public BlastDoor BlastDoor { get; } + + /// + /// Gets or sets the new state. + /// + public bool NewState { get; set; } + + /// + public bool IsAllowed { get; set; } +} diff --git a/LabApi/Events/Arguments/ServerEvents/CassieAnnouncedEventArgs.cs b/LabApi/Events/Arguments/ServerEvents/CassieAnnouncedEventArgs.cs index 2aff367f..b6f3dcf9 100644 --- a/LabApi/Events/Arguments/ServerEvents/CassieAnnouncedEventArgs.cs +++ b/LabApi/Events/Arguments/ServerEvents/CassieAnnouncedEventArgs.cs @@ -13,7 +13,7 @@ public class CassieAnnouncedEventArgs : EventArgs /// The sentence C.A.S.S.I.E. is supposed to say. /// For most cases you wanna keep it true. Sets a minimal 3-second moment of silence before the announcement. /// The background noises before playing. - /// If thats custom announcement? Custom announcements show subtitles + /// If thats custom announcement? Custom announcements show subtitles. /// Custom subtitles text. public CassieAnnouncedEventArgs(string words, bool makeHold, bool makeNoise, bool customAnnouncement, string customSubtitles) { @@ -25,7 +25,7 @@ public CassieAnnouncedEventArgs(string words, bool makeHold, bool makeNoise, boo } /// - /// Gets sentece which C.A.S.S.I.E. said. + /// Gets sentence which C.A.S.S.I.E. said. /// public string Words { get; } diff --git a/LabApi/Events/Arguments/ServerEvents/CassieAnnouncingEventArgs.cs b/LabApi/Events/Arguments/ServerEvents/CassieAnnouncingEventArgs.cs index 0ceb04ad..aac4eda1 100644 --- a/LabApi/Events/Arguments/ServerEvents/CassieAnnouncingEventArgs.cs +++ b/LabApi/Events/Arguments/ServerEvents/CassieAnnouncingEventArgs.cs @@ -14,7 +14,7 @@ public class CassieAnnouncingEventArgs : EventArgs, ICancellableEvent /// The sentence C.A.S.S.I.E. is supposed to say. /// For most cases you wanna keep it true. Sets a minimal 3-second moment of silence before the announcement. /// The background noises before playing. - /// If thats custom announcement? Custom announcements show subtitles + /// If thats custom announcement? Custom announcements show subtitles. /// Custom subtitles text to appear instead of original text. public CassieAnnouncingEventArgs(string words, bool makeHold, bool makeNoise, bool customAnnouncement, string customSubtitles) { @@ -27,7 +27,7 @@ public CassieAnnouncingEventArgs(string words, bool makeHold, bool makeNoise, bo } /// - /// Gets or sets sentece which C.A.S.S.I.E. will say. + /// Gets or sets sentence which C.A.S.S.I.E. will say. /// public string Words { get; set; } diff --git a/LabApi/Events/Arguments/ServerEvents/CassieQueuedScpTerminationEventArgs.cs b/LabApi/Events/Arguments/ServerEvents/CassieQueuedScpTerminationEventArgs.cs index 43d888b2..8ed5dad8 100644 --- a/LabApi/Events/Arguments/ServerEvents/CassieQueuedScpTerminationEventArgs.cs +++ b/LabApi/Events/Arguments/ServerEvents/CassieQueuedScpTerminationEventArgs.cs @@ -1,5 +1,6 @@ using LabApi.Events.Arguments.Interfaces; using LabApi.Features.Wrappers; +using PlayerStatsSystem; using Subtitles; using System; @@ -13,14 +14,16 @@ public class CassieQueuedScpTerminationEventArgs : EventArgs, IPlayerEvent /// /// Initializes a new instance of the class. /// - /// The SCP player the C.A.S.S.I.E termination announcement is for. + /// The SCP player the C.A.S.S.I.E termination announcement is for. /// The message C.A.S.S.I.E is supposed to say. /// The subtitle part array of the message. - public CassieQueuedScpTerminationEventArgs(ReferenceHub player, string announcement, SubtitlePart[] subtitles) + /// The damage handler that caused the termination of the SCP. + public CassieQueuedScpTerminationEventArgs(ReferenceHub hub, string announcement, SubtitlePart[] subtitles, DamageHandlerBase damageHandler) { - Player = Player.Get(player); + Player = Player.Get(hub); Announcement = announcement; SubtitleParts = subtitles; + DamageHandler = damageHandler; } /// @@ -37,4 +40,9 @@ public CassieQueuedScpTerminationEventArgs(ReferenceHub player, string announcem /// Gets or sets the subtitle parts of the message. /// public SubtitlePart[] SubtitleParts { get; } + + /// + /// The Damage Handler responsible for the SCP Termination. + /// + public DamageHandlerBase DamageHandler { get; } } diff --git a/LabApi/Events/Arguments/ServerEvents/CassieQueuingScpTerminationEventArgs.cs b/LabApi/Events/Arguments/ServerEvents/CassieQueuingScpTerminationEventArgs.cs index f94c3e76..437947e5 100644 --- a/LabApi/Events/Arguments/ServerEvents/CassieQueuingScpTerminationEventArgs.cs +++ b/LabApi/Events/Arguments/ServerEvents/CassieQueuingScpTerminationEventArgs.cs @@ -1,5 +1,6 @@ using LabApi.Events.Arguments.Interfaces; using LabApi.Features.Wrappers; +using PlayerStatsSystem; using Subtitles; using System; @@ -13,15 +14,17 @@ public class CassieQueuingScpTerminationEventArgs : EventArgs, IPlayerEvent, ICa /// /// Initializes a new instance of the class. /// - /// The SCP player the C.A.S.S.I.E termination announcement is for. + /// The SCP player the C.A.S.S.I.E termination announcement is for. /// The message C.A.S.S.I.E is supposed to say. /// The subtitle part array of the message. - public CassieQueuingScpTerminationEventArgs(ReferenceHub player, string announcement, SubtitlePart[] subtitles) + /// The damage handler that caused the termination of the SCP. + public CassieQueuingScpTerminationEventArgs(ReferenceHub hub, string announcement, SubtitlePart[] subtitles, DamageHandlerBase damageHandler) { IsAllowed = true; - Player = Player.Get(player); + Player = Player.Get(hub); Announcement = announcement; SubtitleParts = [.. subtitles]; + DamageHandler = damageHandler; } /// @@ -37,8 +40,13 @@ public CassieQueuingScpTerminationEventArgs(ReferenceHub player, string announce /// /// Gets or sets the subtitle parts of the message. /// - public SubtitlePart[] SubtitleParts { get; set; } + public SubtitlePart[] SubtitleParts { get; set; } /// public bool IsAllowed { get; set; } + + /// + /// The Damage Handler responsible for the SCP Termination. + /// + public DamageHandlerBase DamageHandler { get; } } diff --git a/LabApi/Events/Arguments/ServerEvents/CheckpointDoorSequenceChangedEventArgs.cs b/LabApi/Events/Arguments/ServerEvents/CheckpointDoorSequenceChangedEventArgs.cs new file mode 100644 index 00000000..1d1261e0 --- /dev/null +++ b/LabApi/Events/Arguments/ServerEvents/CheckpointDoorSequenceChangedEventArgs.cs @@ -0,0 +1,32 @@ +using LabApi.Features.Wrappers; +using System; +using static Interactables.Interobjects.CheckpointDoor; + +namespace LabApi.Events.Arguments.ServerEvents; + +/// +/// Represents the arguments for the event. +/// +public class CheckpointDoorSequenceChangedEventArgs : EventArgs +{ + /// + /// Initializes a new instance of the class. + /// + /// The current checkpoint door. + /// The current state this checkpoint is. + public CheckpointDoorSequenceChangedEventArgs(Interactables.Interobjects.CheckpointDoor door, SequenceState sequenceState) + { + CheckpointDoor = CheckpointDoor.Get(door); + CurrentSequence = sequenceState; + } + + /// + /// Gets the current Checkpoint Door. + /// + public CheckpointDoor CheckpointDoor { get; } + + /// + /// Gets the damage value. + /// + public SequenceState CurrentSequence { get; } +} diff --git a/LabApi/Events/Arguments/ServerEvents/CheckpointDoorSequenceChangingEventArgs.cs b/LabApi/Events/Arguments/ServerEvents/CheckpointDoorSequenceChangingEventArgs.cs new file mode 100644 index 00000000..2f436c79 --- /dev/null +++ b/LabApi/Events/Arguments/ServerEvents/CheckpointDoorSequenceChangingEventArgs.cs @@ -0,0 +1,45 @@ +using LabApi.Events.Arguments.Interfaces; +using LabApi.Features.Wrappers; +using System; +using static Interactables.Interobjects.CheckpointDoor; + +namespace LabApi.Events.Arguments.ServerEvents; + +/// +/// Represents the arguments for the event. +/// +public class CheckpointDoorSequenceChangingEventArgs : EventArgs, ICancellableEvent +{ + /// + /// Initializes a new instance of the class. + /// + /// The current checkpoint door. + /// The current state this checkpoint is. + /// The new state this checkpoint changing. + public CheckpointDoorSequenceChangingEventArgs(Interactables.Interobjects.CheckpointDoor door, SequenceState oldState, SequenceState sequenceState) + { + CheckpointDoor = CheckpointDoor.Get(door); + CurrentSequence = oldState; + NewSequence = sequenceState; + + IsAllowed = true; + } + + /// + /// Gets the current Checkpoint Door. + /// + public CheckpointDoor CheckpointDoor { get; } + + /// + /// Gets the current sequence state. + /// + public SequenceState CurrentSequence { get; } + + /// + /// Gets or sets the new sequence state. + /// + public SequenceState NewSequence { get; set; } + + /// + public bool IsAllowed { get; set; } +} diff --git a/LabApi/Events/Arguments/ServerEvents/CommandExecutedEventArgs.cs b/LabApi/Events/Arguments/ServerEvents/CommandExecutedEventArgs.cs index c14e0a37..af6d7f31 100644 --- a/LabApi/Events/Arguments/ServerEvents/CommandExecutedEventArgs.cs +++ b/LabApi/Events/Arguments/ServerEvents/CommandExecutedEventArgs.cs @@ -1,7 +1,7 @@ using CommandSystem; +using LabApi.Events.Arguments.Interfaces; using LabApi.Features.Enums; using System; -using LabApi.Events.Arguments.Interfaces; namespace LabApi.Events.Arguments.ServerEvents; @@ -18,7 +18,7 @@ public class CommandExecutedEventArgs : EventArgs, ICommandSenderEvent /// The command. /// The arguments of the command. /// Whether the command was executed successfully. - /// The response of the command + /// The response of the command. public CommandExecutedEventArgs(CommandSender? sender, CommandType commandType, ICommand command, ArraySegment arguments, bool successful, string response) { Sender = sender; diff --git a/LabApi/Events/Arguments/ServerEvents/DeadmanSequenceActivatingEventArgs.cs b/LabApi/Events/Arguments/ServerEvents/DeadmanSequenceActivatingEventArgs.cs new file mode 100644 index 00000000..446482a0 --- /dev/null +++ b/LabApi/Events/Arguments/ServerEvents/DeadmanSequenceActivatingEventArgs.cs @@ -0,0 +1,14 @@ +using LabApi.Events.Arguments.Interfaces; +using System; + +namespace LabApi.Events.Arguments.ServerEvents; + +/// +/// Represents the arguments for the event. +/// +public class DeadmanSequenceActivatingEventArgs : EventArgs, ICancellableEvent +{ + /// + /// Will reset Deadman Sequence timer back to 0 if . + public bool IsAllowed { get; set; } = true; +} \ No newline at end of file diff --git a/LabApi/Events/Arguments/ServerEvents/DoorDamagedEventArgs.cs b/LabApi/Events/Arguments/ServerEvents/DoorDamagedEventArgs.cs new file mode 100644 index 00000000..dc6ce212 --- /dev/null +++ b/LabApi/Events/Arguments/ServerEvents/DoorDamagedEventArgs.cs @@ -0,0 +1,39 @@ +using Interactables.Interobjects.DoorUtils; +using LabApi.Features.Wrappers; +using System; + +namespace LabApi.Events.Arguments.ServerEvents; + +/// +/// Represents the arguments for the event. +/// +public class DoorDamagedEventArgs : EventArgs +{ + /// + /// Initializes a new instance of the class. + /// + /// The door that was damaged. + /// The damage to apply this door. + /// The type of damage this door received. + public DoorDamagedEventArgs(DoorVariant door, float hp, DoorDamageType type) + { + Door = Door.Get(door); + Damage = hp; + DamageType = type; + } + + /// + /// Gets the current Door. + /// + public Door Door { get; } + + /// + /// Gets the damage value. + /// + public float Damage { get; } + + /// + /// Gets the damage type. + /// + public DoorDamageType DamageType { get; } +} diff --git a/LabApi/Events/Arguments/ServerEvents/DoorDamagingEventArgs.cs b/LabApi/Events/Arguments/ServerEvents/DoorDamagingEventArgs.cs new file mode 100644 index 00000000..9114da41 --- /dev/null +++ b/LabApi/Events/Arguments/ServerEvents/DoorDamagingEventArgs.cs @@ -0,0 +1,45 @@ +using Interactables.Interobjects.DoorUtils; +using LabApi.Events.Arguments.Interfaces; +using LabApi.Features.Wrappers; +using System; + +namespace LabApi.Events.Arguments.ServerEvents; + +/// +/// Represents the arguments for the event. +/// +public class DoorDamagingEventArgs : EventArgs, ICancellableEvent +{ + /// + /// Initializes a new instance of the class. + /// + /// The door that is damaging. + /// The damage to apply this door. + /// The type of damage this door received. + public DoorDamagingEventArgs(DoorVariant door, float hp, DoorDamageType type) + { + Door = Door.Get(door); + Damage = hp; + DamageType = type; + + IsAllowed = true; + } + + /// + /// Gets the current Door. + /// + public Door Door { get; } + + /// + /// Gets or sets the damage value. + /// + public float Damage { get; set; } + + /// + /// Gets or sets the damage type. + /// + public DoorDamageType DamageType { get; set; } + + /// + public bool IsAllowed { get; set; } +} diff --git a/LabApi/Events/Arguments/ServerEvents/DoorLockChangedEventArgs.cs b/LabApi/Events/Arguments/ServerEvents/DoorLockChangedEventArgs.cs new file mode 100644 index 00000000..a0f28ac4 --- /dev/null +++ b/LabApi/Events/Arguments/ServerEvents/DoorLockChangedEventArgs.cs @@ -0,0 +1,40 @@ +using Interactables.Interobjects.DoorUtils; +using LabApi.Events.Arguments.Interfaces; +using LabApi.Features.Wrappers; +using System; + +namespace LabApi.Events.Arguments.ServerEvents; + +/// +/// Represents the arguments for the event. +/// +public class DoorLockChangedEventArgs : EventArgs +{ + /// + /// Initializes a new instance of the class. + /// + /// The door whose lock reason changed. + /// The previous lock reason. + /// The 's lock reason. + public DoorLockChangedEventArgs(DoorVariant door, ushort prevLockReason, ushort activeLocks) + { + Door = Door.Get(door); + PrevLockReason = (DoorLockReason)prevLockReason; + LockReason = (DoorLockReason)activeLocks; + } + + /// + /// Gets the current Door. + /// + public Door Door { get; } + + /// + /// Gets the old lock reason. + /// + public DoorLockReason PrevLockReason { get; } + + /// + /// Gets the new lock reason. + /// + public DoorLockReason LockReason { get; } +} diff --git a/LabApi/Events/Arguments/ServerEvents/DoorRepairedEventArgs.cs b/LabApi/Events/Arguments/ServerEvents/DoorRepairedEventArgs.cs new file mode 100644 index 00000000..27aa4d2c --- /dev/null +++ b/LabApi/Events/Arguments/ServerEvents/DoorRepairedEventArgs.cs @@ -0,0 +1,32 @@ +using Interactables.Interobjects.DoorUtils; +using LabApi.Features.Wrappers; +using System; + +namespace LabApi.Events.Arguments.ServerEvents; + +/// +/// Represents the arguments for the event. +/// +public class DoorRepairedEventArgs : EventArgs +{ + /// + /// Initializes a new instance of the class. + /// + /// The door that was repaired. + /// The remaining health for this door. + public DoorRepairedEventArgs(DoorVariant door, float remainingHealth) + { + Door = Door.Get(door); + RemainingHealth = remainingHealth; + } + + /// + /// Gets the current Door. + /// + public Door Door { get; } + + /// + /// Gets the remaining health of the . + /// + public float RemainingHealth { get; } +} diff --git a/LabApi/Events/Arguments/ServerEvents/DoorRepairingEventArgs.cs b/LabApi/Events/Arguments/ServerEvents/DoorRepairingEventArgs.cs new file mode 100644 index 00000000..f9014b99 --- /dev/null +++ b/LabApi/Events/Arguments/ServerEvents/DoorRepairingEventArgs.cs @@ -0,0 +1,38 @@ +using Interactables.Interobjects.DoorUtils; +using LabApi.Events.Arguments.Interfaces; +using LabApi.Features.Wrappers; +using System; + +namespace LabApi.Events.Arguments.ServerEvents; + +/// +/// Represents the arguments for the event. +/// +public class DoorRepairingEventArgs : EventArgs, ICancellableEvent +{ + /// + /// Initializes a new instance of the class. + /// + /// The door that is repairing. + /// The remaining health for this door. + public DoorRepairingEventArgs(DoorVariant door, float remainingHealth) + { + Door = Door.Get(door); + RemainingHealth = remainingHealth; + + IsAllowed = true; + } + + /// + /// Gets the current Door. + /// + public Door Door { get; } + + /// + /// Gets or sets the remaining health of the . + /// + public float RemainingHealth { get; set; } + + /// + public bool IsAllowed { get; set; } +} diff --git a/LabApi/Events/Arguments/ServerEvents/ElevatorSequenceChangedEventArgs.cs b/LabApi/Events/Arguments/ServerEvents/ElevatorSequenceChangedEventArgs.cs new file mode 100644 index 00000000..965bdd42 --- /dev/null +++ b/LabApi/Events/Arguments/ServerEvents/ElevatorSequenceChangedEventArgs.cs @@ -0,0 +1,39 @@ +using Interactables.Interobjects; +using LabApi.Events.Arguments.Interfaces; +using LabApi.Features.Wrappers; +using System; +using static Interactables.Interobjects.ElevatorChamber; + +namespace LabApi.Events.Arguments.ServerEvents; + +/// +/// Represents the arguments for the event. +/// +public class ElevatorSequenceChangedEventArgs : EventArgs, IElevatorEvent +{ + /// + /// Initializes a new instance of the class. + /// + /// The elevator whose sequence has changed. + /// The old sequence the elevator was in before. + /// The new sequence the elevator has transitioned into. + public ElevatorSequenceChangedEventArgs(ElevatorChamber elevator, ElevatorSequence oldSequence, ElevatorSequence newSequence) + { + Elevator = Elevator.Get(elevator); + OldSequence = oldSequence; + NewSequence = newSequence; + } + + /// + public Elevator Elevator { get; } + + /// + /// The old sequence the elevator was in before. + /// + public ElevatorSequence OldSequence { get; } + + /// + /// The new sequence the elevator has transitioned into. + /// + public ElevatorSequence NewSequence { get; } +} diff --git a/LabApi/Events/Arguments/ServerEvents/ExplosionSpawnedEventArgs.cs b/LabApi/Events/Arguments/ServerEvents/ExplosionSpawnedEventArgs.cs index fe56ed15..9a5f1f92 100644 --- a/LabApi/Events/Arguments/ServerEvents/ExplosionSpawnedEventArgs.cs +++ b/LabApi/Events/Arguments/ServerEvents/ExplosionSpawnedEventArgs.cs @@ -4,53 +4,52 @@ using System; using UnityEngine; -namespace LabApi.Events.Arguments.ServerEvents +namespace LabApi.Events.Arguments.ServerEvents; + +/// +/// Represents the arguments for the event. +/// +public class ExplosionSpawnedEventArgs : EventArgs, IPlayerEvent { /// - /// Represents the arguments for the event. + /// Initializes a new instance of the class. /// - public class ExplosionSpawnedEventArgs : EventArgs, IPlayerEvent + /// The player which caused this explosion. + /// The position of explosion. + /// The projectile which caused explosion. + /// The type of this explosion. + /// Whether the explosion was allowed to destroy doors. + public ExplosionSpawnedEventArgs(ReferenceHub? hub, Vector3 position, ExplosionGrenade settingsReference, ExplosionType explosionType, bool destroyDoors) { - /// - /// Initializes a new instance of the class. - /// - /// The player which caused this explosion. - /// The position of explosion. - /// The projectile which caused explosion. - /// The type of this explosion. - /// Whether the explosion was allowed to destroy doors. - public ExplosionSpawnedEventArgs(ReferenceHub? player, Vector3 position, ExplosionGrenade settingsReference, ExplosionType explosionType, bool destroyDoors) - { - Player = Player.Get(player); - Position = position; - Settings = settingsReference; - ExplosionType = explosionType; - DestroyDoors = destroyDoors; - } + Player = Player.Get(hub); + Position = position; + Settings = settingsReference; + ExplosionType = explosionType; + DestroyDoors = destroyDoors; + } - /// - /// Gets the player which caused this explosion. - /// - public Player? Player { get; } + /// + /// Gets the player which caused this explosion. + /// + public Player? Player { get; } - /// - /// Gets the position of explosion. - /// - public Vector3 Position { get; } + /// + /// Gets the position of explosion. + /// + public Vector3 Position { get; } - /// - /// Gets the projectile which will cause explosion. - /// - public ExplosionGrenade Settings { get; } + /// + /// Gets the projectile which will cause explosion. + /// + public ExplosionGrenade Settings { get; } - /// - /// Gets the type of this explosion. - /// - public ExplosionType ExplosionType { get; } + /// + /// Gets the type of this explosion. + /// + public ExplosionType ExplosionType { get; } - /// - /// Gets whether the explosion should destroy doors. - /// - public bool DestroyDoors { get; } - } + /// + /// Gets whether the explosion should destroy doors. + /// + public bool DestroyDoors { get; } } diff --git a/LabApi/Events/Arguments/ServerEvents/ExplosionSpawningEventArgs.cs b/LabApi/Events/Arguments/ServerEvents/ExplosionSpawningEventArgs.cs index 29638552..f6438f2f 100644 --- a/LabApi/Events/Arguments/ServerEvents/ExplosionSpawningEventArgs.cs +++ b/LabApi/Events/Arguments/ServerEvents/ExplosionSpawningEventArgs.cs @@ -4,58 +4,57 @@ using System; using UnityEngine; -namespace LabApi.Events.Arguments.ServerEvents +namespace LabApi.Events.Arguments.ServerEvents; + +/// +/// Represents the arguments for the event. +/// +public class ExplosionSpawningEventArgs : EventArgs, IPlayerEvent, ICancellableEvent { /// - /// Represents the arguments for the event. + /// Initializes a new instance of the class. /// - public class ExplosionSpawningEventArgs : EventArgs, IPlayerEvent, ICancellableEvent + /// The player which caused this explosion. + /// The position of explosion. + /// The projectile which will cause the explosion. + /// The type of this explosion. + /// Whether the explosion should destroy doors. + public ExplosionSpawningEventArgs(ReferenceHub? hub, Vector3 position, ExplosionGrenade settingsReference, ExplosionType explosionType, bool destroyDoors) { - /// - /// Initializes a new instance of the class. - /// - /// The player which caused this explosion. - /// The position of explosion. - /// The projectile which will cause the explosion. - /// The type of this explosion. - /// Whether the explosion should destroy doors. - public ExplosionSpawningEventArgs(ReferenceHub? player, Vector3 position, ExplosionGrenade settingsReference, ExplosionType explosionType, bool destroyDoors) - { - Player = Player.Get(player); - Position = position; - Settings = settingsReference; - ExplosionType = explosionType; - DestroyDoors = destroyDoors; - - IsAllowed = true; - } - - /// - /// Gets or sets the player which caused this explosion. - /// - public Player? Player { get; set; } - - /// - /// Gets or sets the position of explosion. - /// - public Vector3 Position { get; set; } - - /// - /// Gets or sets the projectile which will cause explosion. - /// - public ExplosionGrenade Settings { get; set; } - - /// - /// Gets or sets the type of this explosion. - /// - public ExplosionType ExplosionType { get; set; } - - /// - /// Gets or sets whether the explosion should destroy doors. - /// - public bool DestroyDoors { get; set; } - - /// - public bool IsAllowed { get; set; } + Player = Player.Get(hub); + Position = position; + Settings = settingsReference; + ExplosionType = explosionType; + DestroyDoors = destroyDoors; + + IsAllowed = true; } + + /// + /// Gets or sets the player which caused this explosion. + /// + public Player? Player { get; set; } + + /// + /// Gets or sets the position of explosion. + /// + public Vector3 Position { get; set; } + + /// + /// Gets or sets the projectile which will cause explosion. + /// + public ExplosionGrenade Settings { get; set; } + + /// + /// Gets or sets the type of this explosion. + /// + public ExplosionType ExplosionType { get; set; } + + /// + /// Gets or sets whether the explosion should destroy doors. + /// + public bool DestroyDoors { get; set; } + + /// + public bool IsAllowed { get; set; } } diff --git a/LabApi/Events/Arguments/ServerEvents/ItemSpawningEventArgs.cs b/LabApi/Events/Arguments/ServerEvents/ItemSpawningEventArgs.cs index a1bd6009..92b8368e 100644 --- a/LabApi/Events/Arguments/ServerEvents/ItemSpawningEventArgs.cs +++ b/LabApi/Events/Arguments/ServerEvents/ItemSpawningEventArgs.cs @@ -11,7 +11,7 @@ public class ItemSpawningEventArgs : EventArgs, ICancellableEvent /// /// Initializes a new instance of the class. /// - /// The type of item which will spawn on map + /// The type of item which will spawn on map. public ItemSpawningEventArgs(ItemType type) { IsAllowed = true; diff --git a/LabApi/Events/Arguments/ServerEvents/ModifiedFactionInfluenceEventArgs.cs b/LabApi/Events/Arguments/ServerEvents/ModifiedFactionInfluenceEventArgs.cs new file mode 100644 index 00000000..b967e7eb --- /dev/null +++ b/LabApi/Events/Arguments/ServerEvents/ModifiedFactionInfluenceEventArgs.cs @@ -0,0 +1,32 @@ +using PlayerRoles; +using Respawning; +using System; + +namespace LabApi.Events.Arguments.ServerEvents; + +/// +/// Represents the arguments for the event. +/// +public class ModifiedFactionInfluenceEventArgs : EventArgs +{ + /// + /// Initializes a new instance of the class. + /// + /// The faction whose influence is modified. + /// The influence amount the has now. + public ModifiedFactionInfluenceEventArgs(Faction faction, float influence) + { + Faction = faction; + Influence = influence; + } + + /// + /// Gets the faction whose influence is modified. + /// + public Faction Faction { get; } + + /// + /// Gets the new influence of the . + /// + public float Influence { get; } +} diff --git a/LabApi/Events/Arguments/ServerEvents/ModifyingFactionInfluenceEventArgs.cs b/LabApi/Events/Arguments/ServerEvents/ModifyingFactionInfluenceEventArgs.cs new file mode 100644 index 00000000..66ea997a --- /dev/null +++ b/LabApi/Events/Arguments/ServerEvents/ModifyingFactionInfluenceEventArgs.cs @@ -0,0 +1,38 @@ +using LabApi.Events.Arguments.Interfaces; +using PlayerRoles; +using Respawning; +using System; + +namespace LabApi.Events.Arguments.ServerEvents; + +/// +/// Represents the arguments for the event. +/// +public class ModifyingFactionInfluenceEventArgs : EventArgs, ICancellableEvent +{ + /// + /// Initializes a new instance of the class. + /// + /// The faction whose influence is being modified. + /// The influence amount the has now. + public ModifyingFactionInfluenceEventArgs(Faction faction, float influence) + { + Faction = faction; + Influence = influence; + + IsAllowed = true; + } + + /// + /// Gets or sets the faction whose influence is being modified. + /// + public Faction Faction { get; set; } + + /// + /// Gets or sets the new influence of the . + /// + public float Influence { get; set; } + + /// + public bool IsAllowed { get; set; } +} diff --git a/LabApi/Events/Arguments/ServerEvents/ProjectileExplodedEventArgs.cs b/LabApi/Events/Arguments/ServerEvents/ProjectileExplodedEventArgs.cs index 6144ff08..832fe1f3 100644 --- a/LabApi/Events/Arguments/ServerEvents/ProjectileExplodedEventArgs.cs +++ b/LabApi/Events/Arguments/ServerEvents/ProjectileExplodedEventArgs.cs @@ -15,12 +15,12 @@ public class ProjectileExplodedEventArgs : EventArgs, IPlayerEvent, ITimedGrenad /// Initializes a new instance of the class. /// /// The projectile which will cause explosion. - /// The player which threw that grenade. + /// The player which threw that grenade. /// The position of explosion. - public ProjectileExplodedEventArgs(TimeGrenade projectile, ReferenceHub player, Vector3 position) + public ProjectileExplodedEventArgs(TimeGrenade projectile, ReferenceHub hub, Vector3 position) { TimedGrenade = TimedGrenadeProjectile.Get(projectile); - Player = Player.Get(player); + Player = Player.Get(hub); Position = position; } diff --git a/LabApi/Events/Arguments/ServerEvents/ProjectileExplodingEventArgs.cs b/LabApi/Events/Arguments/ServerEvents/ProjectileExplodingEventArgs.cs index ff5f3dff..31bdfed5 100644 --- a/LabApi/Events/Arguments/ServerEvents/ProjectileExplodingEventArgs.cs +++ b/LabApi/Events/Arguments/ServerEvents/ProjectileExplodingEventArgs.cs @@ -15,12 +15,12 @@ public class ProjectileExplodingEventArgs : EventArgs, IPlayerEvent, ITimedGrena /// Initializes a new instance of the class. /// /// The grenade which will cause explosion. - /// The player which threw that grenade. + /// The player which threw that grenade. /// The position of explosion. - public ProjectileExplodingEventArgs(TimeGrenade grenade, ReferenceHub player, Vector3 position) + public ProjectileExplodingEventArgs(TimeGrenade grenade, ReferenceHub hub, Vector3 position) { TimedGrenade = TimedGrenadeProjectile.Get(grenade); - Player = Player.Get(player); + Player = Player.Get(hub); Position = position; IsAllowed = true; diff --git a/LabApi/Events/Arguments/ServerEvents/RoomColorChangedEventArgs.cs b/LabApi/Events/Arguments/ServerEvents/RoomColorChangedEventArgs.cs new file mode 100644 index 00000000..2eac9d68 --- /dev/null +++ b/LabApi/Events/Arguments/ServerEvents/RoomColorChangedEventArgs.cs @@ -0,0 +1,33 @@ +using LabApi.Features.Wrappers; +using MapGeneration; +using System; +using UnityEngine; + +namespace LabApi.Events.Arguments.ServerEvents; + +/// +/// Represents the arguments for the event. +/// +public class RoomColorChangedEventArgs : EventArgs +{ + /// + /// Initializes a new instance of the class. + /// + /// The room that is changing its color. + /// The 's new color. + public RoomColorChangedEventArgs(RoomIdentifier room, Color newState) + { + Room = Room.Get(room); + NewState = newState; + } + + /// + /// Gets the current room. + /// + public Room Room { get; } + + /// + /// Gets the new color. + /// + public Color NewState { get; } +} diff --git a/LabApi/Events/Arguments/ServerEvents/RoomLightChangedEventArgs.cs b/LabApi/Events/Arguments/ServerEvents/RoomLightChangedEventArgs.cs new file mode 100644 index 00000000..a8a6d4c4 --- /dev/null +++ b/LabApi/Events/Arguments/ServerEvents/RoomLightChangedEventArgs.cs @@ -0,0 +1,32 @@ +using LabApi.Features.Wrappers; +using MapGeneration; +using System; + +namespace LabApi.Events.Arguments.ServerEvents; + +/// +/// Represents the arguments for the event. +/// +public class RoomLightChangedEventArgs : EventArgs +{ + /// + /// Initializes a new instance of the class. + /// + /// The room that is changing its light state. + /// The 's new light state. + public RoomLightChangedEventArgs(RoomIdentifier room, bool newState) + { + Room = Room.Get(room); + NewState = newState; + } + + /// + /// Gets the current room. + /// + public Room Room { get; } + + /// + /// Gets the new light state. + /// + public bool NewState { get; } +} diff --git a/LabApi/Events/Arguments/ServerEvents/RoundEndingConditionsCheckEventArgs.cs b/LabApi/Events/Arguments/ServerEvents/RoundEndingConditionsCheckEventArgs.cs index 4ddd004b..afc3f753 100644 --- a/LabApi/Events/Arguments/ServerEvents/RoundEndingConditionsCheckEventArgs.cs +++ b/LabApi/Events/Arguments/ServerEvents/RoundEndingConditionsCheckEventArgs.cs @@ -10,7 +10,7 @@ public class RoundEndingConditionsCheckEventArgs : EventArgs /// /// Initializes a new instance of the class. /// - /// Whether the round end conditions are met + /// Whether the round end conditions are met. public RoundEndingConditionsCheckEventArgs(bool canEnd) { CanEnd = canEnd; diff --git a/LabApi/Events/Arguments/ServerEvents/SentAdminChatEventArgs.cs b/LabApi/Events/Arguments/ServerEvents/SentAdminChatEventArgs.cs index b9cd0e43..d6a79331 100644 --- a/LabApi/Events/Arguments/ServerEvents/SentAdminChatEventArgs.cs +++ b/LabApi/Events/Arguments/ServerEvents/SentAdminChatEventArgs.cs @@ -1,5 +1,5 @@ -using System; using LabApi.Events.Arguments.Interfaces; +using System; namespace LabApi.Events.Arguments.ServerEvents; diff --git a/LabApi/Events/Arguments/ServerEvents/WaveRespawnedEventArgs.cs b/LabApi/Events/Arguments/ServerEvents/WaveRespawnedEventArgs.cs index 8b930c55..c24cce1a 100644 --- a/LabApi/Events/Arguments/ServerEvents/WaveRespawnedEventArgs.cs +++ b/LabApi/Events/Arguments/ServerEvents/WaveRespawnedEventArgs.cs @@ -18,7 +18,7 @@ public class WaveRespawnedEventArgs : EventArgs public WaveRespawnedEventArgs(SpawnableWaveBase wave, List players) { Players = players; - Wave = RespawnWaves.Get(wave); + Wave = RespawnWaves.Get(wave)!; } /// diff --git a/LabApi/Events/Arguments/ServerEvents/WaveRespawningEventArgs.cs b/LabApi/Events/Arguments/ServerEvents/WaveRespawningEventArgs.cs index 5a0f8683..d648a0b3 100644 --- a/LabApi/Events/Arguments/ServerEvents/WaveRespawningEventArgs.cs +++ b/LabApi/Events/Arguments/ServerEvents/WaveRespawningEventArgs.cs @@ -21,11 +21,13 @@ public class WaveRespawningEventArgs : EventArgs, ICancellableEvent public WaveRespawningEventArgs(SpawnableWaveBase wave, Dictionary roles) { IsAllowed = true; - Wave = RespawnWaves.Get(wave); + Wave = RespawnWaves.Get(wave)!; Roles = DictionaryPool.Get(); foreach (KeyValuePair kvp in roles) + { Roles.Add(Player.Get(kvp.Key), kvp.Value); + } } /// diff --git a/LabApi/Events/Arguments/ServerEvents/WaveTeamSelectedEventArgs.cs b/LabApi/Events/Arguments/ServerEvents/WaveTeamSelectedEventArgs.cs index 3a833c6e..e040abc8 100644 --- a/LabApi/Events/Arguments/ServerEvents/WaveTeamSelectedEventArgs.cs +++ b/LabApi/Events/Arguments/ServerEvents/WaveTeamSelectedEventArgs.cs @@ -15,11 +15,11 @@ public class WaveTeamSelectedEventArgs : EventArgs /// The wave that was selected. public WaveTeamSelectedEventArgs(SpawnableWaveBase wave) { - Wave = RespawnWaves.Get(wave); + Wave = RespawnWaves.Get(wave)!; } /// - /// Gets the spawnable wave. See and its subclasses for more info. + /// Gets the spawnable wave. See and its subclasses for more info. /// public RespawnWave Wave { get; } } \ No newline at end of file diff --git a/LabApi/Events/Arguments/ServerEvents/WaveTeamSelectingEventArgs.cs b/LabApi/Events/Arguments/ServerEvents/WaveTeamSelectingEventArgs.cs index d3ba16e1..e3cc02ae 100644 --- a/LabApi/Events/Arguments/ServerEvents/WaveTeamSelectingEventArgs.cs +++ b/LabApi/Events/Arguments/ServerEvents/WaveTeamSelectingEventArgs.cs @@ -21,7 +21,7 @@ public WaveTeamSelectingEventArgs(SpawnableWaveBase wave) } /// - /// Gets or sets the spawnable wave. See and its subclasses.
+ /// Gets or sets the spawnable wave. See and its subclasses.
/// Use the to set it to a different value. ///
public SpawnableWaveBase Wave { get; set; } diff --git a/LabApi/Events/Arguments/WarheadEvents/WarheadDetonatedEventArgs.cs b/LabApi/Events/Arguments/WarheadEvents/WarheadDetonatedEventArgs.cs index 1dde8d35..77bf3c15 100644 --- a/LabApi/Events/Arguments/WarheadEvents/WarheadDetonatedEventArgs.cs +++ b/LabApi/Events/Arguments/WarheadEvents/WarheadDetonatedEventArgs.cs @@ -12,10 +12,10 @@ public class WarheadDetonatedEventArgs : EventArgs, IPlayerEvent /// /// Initializes a new instance of the class. /// - /// The player who detonated the warhead. - public WarheadDetonatedEventArgs(ReferenceHub player) + /// The player who detonated the warhead. + public WarheadDetonatedEventArgs(ReferenceHub hub) { - Player = Player.Get(player); + Player = Player.Get(hub); } /// diff --git a/LabApi/Events/Arguments/WarheadEvents/WarheadDetonatingEventArgs.cs b/LabApi/Events/Arguments/WarheadEvents/WarheadDetonatingEventArgs.cs index b0b0710b..30341c7a 100644 --- a/LabApi/Events/Arguments/WarheadEvents/WarheadDetonatingEventArgs.cs +++ b/LabApi/Events/Arguments/WarheadEvents/WarheadDetonatingEventArgs.cs @@ -12,11 +12,11 @@ public class WarheadDetonatingEventArgs : EventArgs, IPlayerEvent, ICancellableE /// /// Initializes a new instance of the class. /// - /// The player who is detonating the warhead. - public WarheadDetonatingEventArgs(ReferenceHub player) + /// The player who is detonating the warhead. + public WarheadDetonatingEventArgs(ReferenceHub hub) { IsAllowed = true; - Player = Player.Get(player); + Player = Player.Get(hub); } /// diff --git a/LabApi/Events/Arguments/WarheadEvents/WarheadStartedEventArgs.cs b/LabApi/Events/Arguments/WarheadEvents/WarheadStartedEventArgs.cs index 1d2c1e57..7a7ea1a2 100644 --- a/LabApi/Events/Arguments/WarheadEvents/WarheadStartedEventArgs.cs +++ b/LabApi/Events/Arguments/WarheadEvents/WarheadStartedEventArgs.cs @@ -12,13 +12,13 @@ public class WarheadStartedEventArgs : EventArgs, IPlayerEvent /// /// Initializes a new instance of the class. /// - /// The player who started the warhead. + /// The player who started the warhead. /// Whether the warhead is starting automatically. /// Whether subtitles should be suppressed. /// The current state of the alpha warhead. - public WarheadStartedEventArgs(ReferenceHub player, bool isAutomatic, bool suppressSubtitles, AlphaWarheadSyncInfo warheadState) + public WarheadStartedEventArgs(ReferenceHub hub, bool isAutomatic, bool suppressSubtitles, AlphaWarheadSyncInfo warheadState) { - Player = Player.Get(player); + Player = Player.Get(hub); IsAutomatic = isAutomatic; SuppressSubtitles = suppressSubtitles; WarheadState = warheadState; diff --git a/LabApi/Events/Arguments/WarheadEvents/WarheadStartingEventArgs.cs b/LabApi/Events/Arguments/WarheadEvents/WarheadStartingEventArgs.cs index e9dd99eb..39953b1d 100644 --- a/LabApi/Events/Arguments/WarheadEvents/WarheadStartingEventArgs.cs +++ b/LabApi/Events/Arguments/WarheadEvents/WarheadStartingEventArgs.cs @@ -12,14 +12,14 @@ public class WarheadStartingEventArgs : EventArgs, IPlayerEvent, ICancellableEve /// /// Initializes a new instance of the class. /// - /// The player who is starting the warhead. + /// The player who is starting the warhead. /// Whether the warhead is starting automatically. /// Whether subtitles should be suppressed. /// The current state of the alpha warhead. - public WarheadStartingEventArgs(ReferenceHub player, bool isAutomatic, bool suppressSubtitles, AlphaWarheadSyncInfo warheadState) + public WarheadStartingEventArgs(ReferenceHub hub, bool isAutomatic, bool suppressSubtitles, AlphaWarheadSyncInfo warheadState) { IsAllowed = true; - Player = Player.Get(player); + Player = Player.Get(hub); IsAutomatic = isAutomatic; SuppressSubtitles = suppressSubtitles; WarheadState = warheadState; diff --git a/LabApi/Events/Arguments/WarheadEvents/WarheadStoppedEventArgs.cs b/LabApi/Events/Arguments/WarheadEvents/WarheadStoppedEventArgs.cs index 580ace8c..a2894c34 100644 --- a/LabApi/Events/Arguments/WarheadEvents/WarheadStoppedEventArgs.cs +++ b/LabApi/Events/Arguments/WarheadEvents/WarheadStoppedEventArgs.cs @@ -12,11 +12,11 @@ public class WarheadStoppedEventArgs : EventArgs, IPlayerEvent /// /// Initializes a new instance of the class. /// - /// The player who stopped the warhead. + /// The player who stopped the warhead. /// The current state of the alpha warhead. - public WarheadStoppedEventArgs(ReferenceHub player, AlphaWarheadSyncInfo warheadState) + public WarheadStoppedEventArgs(ReferenceHub hub, AlphaWarheadSyncInfo warheadState) { - Player = Player.Get(player); + Player = Player.Get(hub); WarheadState = warheadState; } diff --git a/LabApi/Events/Arguments/WarheadEvents/WarheadStoppingEventArgs.cs b/LabApi/Events/Arguments/WarheadEvents/WarheadStoppingEventArgs.cs index 2812562a..fc39a2ae 100644 --- a/LabApi/Events/Arguments/WarheadEvents/WarheadStoppingEventArgs.cs +++ b/LabApi/Events/Arguments/WarheadEvents/WarheadStoppingEventArgs.cs @@ -12,12 +12,12 @@ public class WarheadStoppingEventArgs : EventArgs, IPlayerEvent, ICancellableEve /// /// Initializes a new instance of the class. /// - /// The player who is stopping the warhead. + /// The player who is stopping the warhead. /// The current state of the alpha warhead. - public WarheadStoppingEventArgs(ReferenceHub player, AlphaWarheadSyncInfo warheadState) + public WarheadStoppingEventArgs(ReferenceHub hub, AlphaWarheadSyncInfo warheadState) { IsAllowed = true; - Player = Player.Get(player); + Player = Player.Get(hub); WarheadState = warheadState; } diff --git a/LabApi/Events/CustomHandlers/CustomEventHandlers.cs b/LabApi/Events/CustomHandlers/CustomEventHandlers.cs index 796c2682..c993a346 100644 --- a/LabApi/Events/CustomHandlers/CustomEventHandlers.cs +++ b/LabApi/Events/CustomHandlers/CustomEventHandlers.cs @@ -12,5 +12,5 @@ public abstract partial class CustomEventsHandler /// /// Internal dictionary to store the registered events and their delegates. /// - internal readonly Dictionary InternalEvents = new (); + internal Dictionary InternalEvents { get; } = []; } \ No newline at end of file diff --git a/LabApi/Events/CustomHandlers/CustomHandlersManager.cs b/LabApi/Events/CustomHandlers/CustomHandlersManager.cs index ba3c7326..8ec32dc8 100644 --- a/LabApi/Events/CustomHandlers/CustomHandlersManager.cs +++ b/LabApi/Events/CustomHandlers/CustomHandlersManager.cs @@ -46,15 +46,32 @@ public static void UnregisterEventsHandler(T handler) /// /// Checks if the event is overriden and subscribes the handler to the event if it is. /// - private static void CheckEvent(T handler, Type handlerType, string methodDelegate, Type eventType, string eventName) + /// The custom event handler instance. + /// The of the handler instance. + /// The of the event method. + /// The class of the handler. + /// The the event in the handler. + /// The custom event handler type. + public static void CheckEvent(T handler, Type handlerType, string methodDelegate, Type eventType, string eventName) where T : CustomEventsHandler { - // We first get the method from the handler. - MethodInfo? method = handlerType.GetMethod(methodDelegate, BindingFlags.Public | BindingFlags.Instance); + // We first get the method from the handler, there can be custom methods names as the original events but with different overloads, so we filter them. + MethodInfo[] candidates = handlerType.GetMethods(BindingFlags.Public | BindingFlags.Instance); - // If the method is null or not an override, we return. - if (method == null || !IsOverride(method)) + MethodInfo? method = null; + foreach (MethodInfo candidate in candidates) + { + if (candidate.Name == methodDelegate && IsOverride(candidate)) + { + method = candidate; + break; + } + } + + if (method == null) + { return; + } // We get the event from the event type. EventInfo eventInfo = eventType.GetEvent(eventName); diff --git a/LabApi/Events/EventManager.cs b/LabApi/Events/EventManager.cs index 85876068..17e15c50 100644 --- a/LabApi/Events/EventManager.cs +++ b/LabApi/Events/EventManager.cs @@ -21,7 +21,9 @@ public static void InvokeEvent(this LabEventHandler? eventHandler) { // We check if the event handler is null if (eventHandler is null) + { return; + } #if DEBUG // In DEBUG mode we add some useful logs about the event. @@ -35,7 +37,9 @@ public static void InvokeEvent(this LabEventHandler? eventHandler) { // We invoke the subscriber as a lab event handler. if (sub is LabEventHandler labEventHandler) + { labEventHandler.Invoke(); + } } catch (Exception e) { @@ -55,7 +59,9 @@ public static void InvokeEvent(this LabEventHandler? eve { // We check if the event handler is null if (eventHandler is null) + { return; + } #if DEBUG // In DEBUG mode we add some useful logs about the event. @@ -69,7 +75,9 @@ public static void InvokeEvent(this LabEventHandler? eve { // We invoke the subscriber as a lab event handler. if (sub is LabEventHandler labEventHandler) + { labEventHandler.Invoke(args); + } } catch (Exception e) { @@ -105,7 +113,9 @@ public static string FormatToString(this LabEventHandler // We iterate through all the properties of the EventArgs and append them to the StringBuilder. PropertyInfo[] properties = typeof(TEventArgs).GetProperties(); if (properties.Length > 0) + { stringBuilder.Append("\n"); + } foreach (PropertyInfo property in properties) { @@ -133,12 +143,14 @@ public static string FormatToString(this LabEventHandler /// /// The that caused the error. /// The that occurred. - /// + /// The formated error message. public static string FormatErrorMessage(Delegate eventHandler, Exception exception) { if (eventHandler.Target == null) // Static methods - return $"'{exception.GetType().Name}' occured while invoking '{eventHandler.Method.Name}' on '{eventHandler.Method.DeclaringType}': '{exception.Message}', stack trace:\n{exception.StackTrace}"; + { + return $"'{exception.GetType().Name}' occurred while invoking '{eventHandler.Method.Name}' on '{eventHandler.Method.DeclaringType}': '{exception.Message}', stack trace:\n{exception.StackTrace}"; + } - return $"'{exception.GetType().Name}' occured while invoking '{eventHandler.Method.Name}' on '{eventHandler.Target.GetType().FullName}': '{exception.Message}', stack trace:\n{exception.StackTrace}"; + return $"'{exception.GetType().Name}' occurred while invoking '{eventHandler.Method.Name}' on '{eventHandler.Target.GetType().FullName}': '{exception.Message}', stack trace:\n{exception.StackTrace}"; } } \ No newline at end of file diff --git a/LabApi/Events/Handlers/ObjectiveEvents.EventHandlers.cs b/LabApi/Events/Handlers/ObjectiveEvents.EventHandlers.cs new file mode 100644 index 00000000..a1404722 --- /dev/null +++ b/LabApi/Events/Handlers/ObjectiveEvents.EventHandlers.cs @@ -0,0 +1,77 @@ +using LabApi.Events.Arguments.ObjectiveEvents; + +namespace LabApi.Events.Handlers; + +/// +/// Handles all events related to objectives. +/// +public static partial class ObjectiveEvents +{ + /// + /// Gets called when any objective is being completed.
+ /// Use specific events or the subclasses of the to determine which kind of the objective is being completed. + ///
+ /// + /// This event is called after the very specific objective event has been triggered. + /// + public static event LabEventHandler? Completing; + + /// + /// Gets called when any objective has been completed.
+ /// Use specific events or the subclasses of the to determine which kind of the objective has been completed. + ///
+ /// + /// This event is called after the very specific objective event has been triggered. + /// + public static event LabEventHandler? Completed; + + /// + /// Gets called when the enemy kill objective is being completed. + /// + public static event LabEventHandler? KillingEnemyCompleting; + + /// + /// Gets called when the enemy kill objective has been completed. + /// + public static event LabEventHandler? KilledEnemyCompleted; + + /// + /// Gets called when the player escape objective is being completed. + /// + public static event LabEventHandler? EscapingCompleting; + + /// + /// Gets called when the player escape objective has been completed. + /// + public static event LabEventHandler? EscapedCompleted; + + /// + /// Gets called when the generator activated objective is being completed. + /// + public static event LabEventHandler? ActivatingGeneratorCompleting; + + /// + /// Gets called when the generator activated objective has been completed. + /// + public static event LabEventHandler? ActivatedGeneratorCompleted; + + /// + /// Gets called when the scp damage objective is being completed. + /// + public static event LabEventHandler? DamagingScpCompleting; + + /// + /// Gets called when the scp damage objective has been completed. + /// + public static event LabEventHandler? DamagedScpCompleted; + + /// + /// Gets called when the scp item pickup objective is being completed. + /// + public static event LabEventHandler? PickingScpItemCompleting; + + /// + /// Gets called when the scp item pickup objective has been completed. + /// + public static event LabEventHandler? PickedScpItemCompleted; +} diff --git a/LabApi/Events/Handlers/PlayerEvents.EventHandlers.cs b/LabApi/Events/Handlers/PlayerEvents.EventHandlers.cs index b33a6643..bd9e2ac2 100644 --- a/LabApi/Events/Handlers/PlayerEvents.EventHandlers.cs +++ b/LabApi/Events/Handlers/PlayerEvents.EventHandlers.cs @@ -49,7 +49,7 @@ public static partial class PlayerEvents ///
public static event LabEventHandler? UsedIntercom; - #endregion + #endregion #region Moderation @@ -123,6 +123,64 @@ public static partial class PlayerEvents ///
public static event LabEventHandler? ToggledNoclip; + /// + /// Gets called when the player is requesting the remote admin player list. + /// + public static event LabEventHandler? RequestingRaPlayerList; + + /// + /// Gets called when the player had requested the remote admin player list. + /// + public static event LabEventHandler? RequestedRaPlayerList; + + /// + /// Gets called when adding a target player to the remote admin player list while processing the request for the player. + /// + public static event LabEventHandler? RaPlayerListAddingPlayer; + + /// + /// Gets called when a target player was added to the remote admin player list while processing the request for the player. + /// + public static event LabEventHandler? RaPlayerListAddedPlayer; + + /// + /// Gets called when a player requested info for an unknown target in the remote admin. + /// + public static event LabEventHandler? RequestedCustomRaInfo; + + /// + /// Gets called when a player is requesting info for multiple players in the remote admin. + /// + public static event LabEventHandler? RequestingRaPlayersInfo; + + /// + /// Gets called when a player had requested info for multiple players in the remote admin. + /// + public static event LabEventHandler? RequestedRaPlayersInfo; + + /// + /// Gets called when a player is requesting info for a target player in the remote admin. + /// + public static event LabEventHandler? RequestingRaPlayerInfo; + + /// + /// Gets called when a player had requested info for a target player in the remote admin. + /// + public static event LabEventHandler? RequestedRaPlayerInfo; + + #endregion + + #region Badges + + /// + /// Gets called when the player is changing their global or local badge visibility. + /// + public static event LabEventHandler? ChangingBadgeVisibility; + + /// + /// Gets called when the player has changed their global or local badge visibility. + /// + public static event LabEventHandler? ChangedBadgeVisibility; #endregion @@ -357,6 +415,31 @@ public static partial class PlayerEvents /// public static event LabEventHandler? ThrewProjectile; + /// + /// Gets called when the player wants to inspect any keycard item. + /// + public static event LabEventHandler? InspectingKeycard; + + /// + /// Gets called when the player inspected keycard item. + /// + public static event LabEventHandler? InspectedKeycard; + + /// + /// Gets called when the player requests to spin the revolver. + /// + public static event LabEventHandler? SpinningRevolver; + + /// + /// Gets called when the player spinned the revolver. + /// + public static event LabEventHandler? SpinnedRevolver; + + /// + /// Gets called when the player toggled disruptor firing mode. + /// + public static event LabEventHandler? ToggledDisruptorFiringMode; + #endregion #region Item Actions and Interactions @@ -371,6 +454,11 @@ public static partial class PlayerEvents /// public static event LabEventHandler? UsedItem; + /// + /// Gets called when the player is about to complete using an item. + /// + public static event LabEventHandler? ItemUsageEffectsApplying; + /// /// Gets called when the player is using the radio. /// @@ -384,7 +472,7 @@ public static partial class PlayerEvents ///// ///// Gets called when the player is aiming the weapon. ///// - //public static event LabEventHandler? AimingWeapon; + // public static event LabEventHandler? AimingWeapon; /// /// Gets called when the player aimed the weapon. @@ -431,6 +519,26 @@ public static partial class PlayerEvents /// public static event LabEventHandler? ShotWeapon; + /// + /// Gets called when player is changing weapon attachments. + /// + public static event LabEventHandler? ChangingAttachments; + + /// + /// Gets called when player has changed weapon attachments. + /// + public static event LabEventHandler? ChangedAttachments; + + /// + /// Gets called when player is changing weapon attachments preferences. + /// + public static event LabEventHandler? SendingAttachmentsPrefs; + + /// + /// Gets called when player has changed weapon attachments preferences. + /// + public static event LabEventHandler? SentAttachmentsPrefs; + /// /// Gets called when the player is cancelling the use of an item. /// @@ -451,6 +559,16 @@ public static partial class PlayerEvents /// public static event LabEventHandler? ChangedRadioRange; + /// + /// Gets called when processing a player's interaction with the jailbird item. + /// + public static event LabEventHandler? ProcessingJailbirdMessage; + + /// + /// Gets called when processed the player's interaction with the jailbird item. + /// + public static event LabEventHandler? ProcessedJailbirdMessage; + /// /// Gets called when the player is toggling a flashlight. /// @@ -481,6 +599,16 @@ public static partial class PlayerEvents /// public static event LabEventHandler? ToggledRadio; + /// + /// Gets called when player successfully jumps. Not called when jumping is prevented by status effects. + /// + public static event LabEventHandler? Jumped; + + /// + /// Gets called when player's movement state change. Such as from walking to running, sneaking and opposite way around. + /// + public static event LabEventHandler? MovementStateChanged; + #endregion #region World Interaction @@ -730,6 +858,46 @@ public static partial class PlayerEvents /// public static event LabEventHandler? UnlockedWarheadButton; + /// + /// Gets called when the player has meet the requirements of an achievement. + /// + public static event LabEventHandler? ReceivedAchievement; + + /// + /// Gets called when player's last known room changes. + /// + public static event LabEventHandler? RoomChanged; + + /// + /// Gets called when player's last known zone changes. + /// + public static event LabEventHandler? ZoneChanged; + + /// + /// Gets called when player interacts with warhead lever. + /// + public static event LabEventHandler? InteractingWarheadLever; + + /// + /// Gets called when player interacted with warhead lever. + /// + public static event LabEventHandler? InteractedWarheadLever; + + /// + /// Gets called when a hitmarker is being sent to a player. + /// + public static event LabEventHandler? SendingHitmarker; + + /// + /// Gets called when a hitmarker is sent to a player. + /// + public static event LabEventHandler? SentHitmarker; + + /// + /// Gets called when a hitmarker permission is checked for a player. + /// + public static event LabEventHandler? CheckedHitmarker; + #endregion #region Spectating @@ -772,5 +940,15 @@ public static partial class PlayerEvents /// Gets called when a player has validated the visibility of a target player. /// public static event LabEventHandler? ValidatedVisibility; + + #endregion + + #region Scp1344 + + /// + /// Gets called when player detects enemy player using SCP-1344. + /// + public static event LabEventHandler? DetectedByScp1344; + #endregion } \ No newline at end of file diff --git a/LabApi/Events/Handlers/Scp0492Events.EventHandlers.cs b/LabApi/Events/Handlers/Scp0492Events.EventHandlers.cs index 9ada9a92..cfd1e490 100644 --- a/LabApi/Events/Handlers/Scp0492Events.EventHandlers.cs +++ b/LabApi/Events/Handlers/Scp0492Events.EventHandlers.cs @@ -11,17 +11,17 @@ public static partial class Scp0492Events /// Gets called when SCP-049-2 is starting to consume a corpse. /// public static event LabEventHandler? StartingConsumingCorpse; - + /// /// Gets called when SCP-049-2 started to consume a corpse. /// public static event LabEventHandler? StartedConsumingCorpse; - + /// /// Gets called when SCP-049-2 is consuming a corpse. /// public static event LabEventHandler? ConsumingCorpse; - + /// /// Gets called when SCP-049-2 consumed a corpse. /// diff --git a/LabApi/Events/Handlers/Scp049Events.EventHandlers.cs b/LabApi/Events/Handlers/Scp049Events.EventHandlers.cs index cc92149d..7e632c77 100644 --- a/LabApi/Events/Handlers/Scp049Events.EventHandlers.cs +++ b/LabApi/Events/Handlers/Scp049Events.EventHandlers.cs @@ -41,4 +41,24 @@ public static partial class Scp049Events /// Gets called when SCP-049 has used its sense ability. /// public static event LabEventHandler? UsedSense; + + /// + /// Gets called when SCP-049 is using its attack ability. + /// + public static event LabEventHandler? Attacking; + + /// + /// Gets called when SCP-049 has used its attack ability. + /// + public static event LabEventHandler? Attacked; + + /// + /// Gets called when SCP-049 has lost a target. + /// + public static event LabEventHandler? SenseLostTarget; + + /// + /// Gets called when SCP-049 has killed a target. + /// + public static event LabEventHandler? SenseKilledTarget; } \ No newline at end of file diff --git a/LabApi/Events/Handlers/Scp127Events.EventHandlers.cs b/LabApi/Events/Handlers/Scp127Events.EventHandlers.cs new file mode 100644 index 00000000..27058f3a --- /dev/null +++ b/LabApi/Events/Handlers/Scp127Events.EventHandlers.cs @@ -0,0 +1,39 @@ +using LabApi.Events.Arguments.Scp127Events; + +namespace LabApi.Events.Handlers; + +/// +/// Handles all the events related to the SCP-127. +/// +public static partial class Scp127Events +{ + /// + /// Gets called when the SCP-127 is gaining experience. + /// + public static event LabEventHandler? GainingExperience; + + /// + /// Gets called when the SCP-127 is gained experience. + /// + public static event LabEventHandler? GainExperience; + + /// + /// Gets called when the SCP-127 is levelling up. + /// + public static event LabEventHandler? LevellingUp; + + /// + /// Gets called when the SCP-127 level up. + /// + public static event LabEventHandler? LevelUp; + + /// + /// Gets called when SCP-127 is about to play a voiceline. + /// + public static event LabEventHandler? Talking; + + /// + /// Gets called when SCP-127 played a voiceline. + /// + public static event LabEventHandler? Talked; +} diff --git a/LabApi/Events/Handlers/Scp173Events.EventHandlers.cs b/LabApi/Events/Handlers/Scp173Events.EventHandlers.cs index dd597691..a6886da6 100644 --- a/LabApi/Events/Handlers/Scp173Events.EventHandlers.cs +++ b/LabApi/Events/Handlers/Scp173Events.EventHandlers.cs @@ -56,4 +56,24 @@ public static partial class Scp173Events /// Gets called when SCP-173 has played a sound. /// public static event LabEventHandler? PlayedSound; + + /// + /// Gets called when SCP-173 is teleporting. + /// + public static event LabEventHandler? Teleporting; + + /// + /// Gets called when SCP-173 has teleported. + /// + public static event LabEventHandler? Teleported; + + /// + /// Gets called when SCP-173 is attempting to snap a target. + /// + public static event LabEventHandler? Snapping; + + /// + /// Gets called when SCP-173 has snapped a target. + /// + public static event LabEventHandler? Snapped; } \ No newline at end of file diff --git a/LabApi/Events/Handlers/Scp3114Events.EventHandlers.cs b/LabApi/Events/Handlers/Scp3114Events.EventHandlers.cs new file mode 100644 index 00000000..8eb5332a --- /dev/null +++ b/LabApi/Events/Handlers/Scp3114Events.EventHandlers.cs @@ -0,0 +1,59 @@ +using LabApi.Events.Arguments.Scp3114Events; + +namespace LabApi.Events.Handlers; + +/// +/// Handles all events related to SCP-3114. +/// +public static partial class Scp3114Events +{ + /// + /// Gets called when SCP-3114 is disguising itself. + /// + public static event LabEventHandler? Disguising; + + /// + /// Gets called when SCP-3114 has disguised itself. + /// + public static event LabEventHandler? Disguised; + + /// + /// Gets called when SCP-3114 is revealing itself. + /// + public static event LabEventHandler? Revealing; + + /// + /// Gets called when SCP-3114 has revealed itself. + /// + public static event LabEventHandler? Revealed; + + /// + /// Gets called when SCP-3114 is starting to strangle a player. + /// + public static event LabEventHandler? StrangleStarting; + + /// + /// Gets called when SCP-3114 has started to strangle a player. + /// + public static event LabEventHandler? StrangleStarted; + + /// + /// Gets called when SCP-3114 is aborting their strangle on the player. + /// + public static event LabEventHandler? StrangleAborting; + + /// + /// Gets called when SCP-3114 started dancing. + /// + public static event LabEventHandler? Dance; + + /// + /// Gets called when SCP-3114 is about to dance. + /// + public static event LabEventHandler? StartDancing; + + /// + /// Gets called when SCP-3114 has aborted their strangle on the player. + /// + public static event LabEventHandler? StrangleAborted; +} \ No newline at end of file diff --git a/LabApi/Events/Handlers/Scp939Events.EventHandlers.cs b/LabApi/Events/Handlers/Scp939Events.EventHandlers.cs index b322067f..ac815205 100644 --- a/LabApi/Events/Handlers/Scp939Events.EventHandlers.cs +++ b/LabApi/Events/Handlers/Scp939Events.EventHandlers.cs @@ -36,4 +36,19 @@ public static partial class Scp939Events /// Gets called when SCP-939 has lunged. /// public static event LabEventHandler? Lunged; + + /// + /// Gets called when SCP-939 has focused. + /// + public static event LabEventHandler? Focused; + + /// + /// Gets called when SCP-939 is mimicking the environment. + /// + public static event LabEventHandler? MimickingEnvironment; + + /// + /// Gets called when SCP-939 has mimicked the environment. + /// + public static event LabEventHandler? MimickedEnvironment; } \ No newline at end of file diff --git a/LabApi/Events/Handlers/ScpEvents.EventHandlers.cs b/LabApi/Events/Handlers/ScpEvents.EventHandlers.cs new file mode 100644 index 00000000..1e1acac2 --- /dev/null +++ b/LabApi/Events/Handlers/ScpEvents.EventHandlers.cs @@ -0,0 +1,14 @@ +using LabApi.Events.Arguments.ScpEvents; + +namespace LabApi.Events.Handlers; + +/// +/// Handles all events related to SCPs. +/// +public static partial class ScpEvents +{ + /// + /// Gets called when an SCP has their hume shield broken. + /// + public static event LabEventHandler? HumeShieldBroken; +} \ No newline at end of file diff --git a/LabApi/Events/Handlers/ServerEvents.EventHandlers.cs b/LabApi/Events/Handlers/ServerEvents.EventHandlers.cs index 7c8ea582..22c977bc 100644 --- a/LabApi/Events/Handlers/ServerEvents.EventHandlers.cs +++ b/LabApi/Events/Handlers/ServerEvents.EventHandlers.cs @@ -17,6 +17,21 @@ public static partial class ServerEvents /// public static event LabEventHandler? RoundRestarted; + /// + /// Gets called when the server shuts down. + /// + public static event LabEventHandler? Shutdown; + + /// + /// Gets called when Deadman Sequence is activated. + /// + public static event LabEventHandler? DeadmanSequenceActivated; + + /// + /// Gets called when Deadman Sequence is activating. + /// + public static event LabEventHandler? DeadmanSequenceActivating; + /// /// Gets called when round end conditions are checked. /// @@ -118,7 +133,7 @@ public static partial class ServerEvents public static event LabEventHandler? LczDecontaminationAnnounced; /// - /// Gets called when the server starts LCZ decontamiantion. + /// Gets called when the server starts LCZ decontamination. /// public static event LabEventHandler? LczDecontaminationStarting; @@ -141,7 +156,7 @@ public static partial class ServerEvents /// Gets called when the server has created a new pickup. /// public static event LabEventHandler? PickupCreated; - + /// /// Gets called when the server has destroyed a pickup. /// @@ -151,7 +166,7 @@ public static partial class ServerEvents /// Gets called when the server is sending an Admin Chat message. /// public static event LabEventHandler? SendingAdminChat; - + /// /// Gets called when the server sent an Admin Chat message. /// @@ -206,4 +221,84 @@ public static partial class ServerEvents /// Gets called when the server activated generator. /// public static event LabEventHandler? GeneratorActivated; + + /// + /// Gets called when elevator's sequence has changed. + /// + public static event LabEventHandler? ElevatorSequenceChanged; + + /// + /// Gets called when a faction's influence is changing. + /// + public static event LabEventHandler? ModifyingFactionInfluence; + + /// + /// Gets called when a faction's influence has changed. + /// + public static event LabEventHandler? ModifiedFactionInfluence; + + /// + /// Gets called when a faction is achieving a milestone. + /// + public static event LabEventHandler? AchievingMilestone; + + /// + /// Gets called when a faction achieved a milestone. + /// + public static event LabEventHandler? AchievedMilestone; + + /// + /// Gets called when a blast door changes state. + /// + public static event LabEventHandler? BlastDoorChanging; + + /// + /// Gets called when a blast door is changed state. + /// + public static event LabEventHandler? BlastDoorChanged; + + /// + /// Gets called when a room's light is changed. + /// + public static event LabEventHandler? RoomLightChanged; + + /// + /// Gets called when a room's color is changed. + /// + public static event LabEventHandler? RoomColorChanged; + + /// + /// Gets called when a door's lock state is changed. + /// + public static event LabEventHandler? DoorLockChanged; + + /// + /// Gets called when a door is repairing. + /// + public static event LabEventHandler? DoorRepairing; + + /// + /// Gets called when a door is repaired. + /// + public static event LabEventHandler? DoorRepaired; + + /// + /// Gets called when a door is damaging. + /// + public static event LabEventHandler? DoorDamaging; + + /// + /// Gets called when a door is damaged. + /// + public static event LabEventHandler? DoorDamaged; + + /// + /// Gets called when a checkpoint door sequence is changing. + /// + public static event LabEventHandler? CheckpointDoorSequenceChanging; + + /// + /// Gets called when a checkpoint door sequence is changed. + /// + public static event LabEventHandler? CheckpointDoorSequenceChanged; } \ No newline at end of file diff --git a/LabApi/Events/LabEventHandlerTEventArgs.cs b/LabApi/Events/LabEventHandler{TEventArgs}.cs similarity index 88% rename from LabApi/Events/LabEventHandlerTEventArgs.cs rename to LabApi/Events/LabEventHandler{TEventArgs}.cs index 8690f875..9452b0fa 100644 --- a/LabApi/Events/LabEventHandlerTEventArgs.cs +++ b/LabApi/Events/LabEventHandler{TEventArgs}.cs @@ -6,6 +6,7 @@ namespace LabApi.Events; /// LabAPI's event handler with a parameter. /// Called when an event is with the specified triggered . /// +/// The event arg instance. /// The type of the of the event. public delegate void LabEventHandler(TEventArgs ev) where TEventArgs : EventArgs; \ No newline at end of file diff --git a/LabApi/Features/Audio/AudioTransmitter.cs b/LabApi/Features/Audio/AudioTransmitter.cs index b90f5801..dfb516ca 100644 --- a/LabApi/Features/Audio/AudioTransmitter.cs +++ b/LabApi/Features/Audio/AudioTransmitter.cs @@ -17,17 +17,11 @@ namespace LabApi.Features.Audio; /// Encodes and sends audio to certain players which plays on speakers with the specified controller id. /// /// -/// Its possible to create multiple transmitters with the same controller id, but you must filter the receiving players such that no one player receives audio from multiple transmitters. +/// Its possible to create multiple transmitters with the same controller id, but you must filter the receiving players such that no one player receives audio from multiple transmitters. /// This is done to allow you to send different audio to certain players using the same speakers. /// public class AudioTransmitter { - private static readonly float[] EmptyData = new float[FrameSize]; - - private static readonly float[] TempSampleData = new float[FrameSize]; - - private static readonly byte[] TempEncodedData = new byte[MaxEncodedSize]; - /// /// The sample rate in samples per second. /// @@ -48,16 +42,39 @@ public class AudioTransmitter /// public const int MaxEncodedSize = VoiceChatSettings.MaxEncodedSize; + private const float GainCorrectionFactor = 1.41421356237f; + + private static readonly float[] EmptyData = new float[FrameSize]; + private static readonly float[] TempSampleData = new float[FrameSize]; + private static readonly byte[] TempEncodedData = new byte[MaxEncodedSize]; + + private readonly OpusEncoder _opusEncoder; + private CoroutineHandle _update; + private double _targetTime = 0.0; + private bool _breakCurrent = false; + private float[] _currentSamples = EmptyData; + + /// + /// Creates a new audio transmitter for the specified controller. + /// + /// The controller specified by its Id. + /// What kind of audio the encoder should optimise's for. + public AudioTransmitter(byte controllerId, OpusApplicationType type = OpusApplicationType.Audio) + { + ControllerId = controllerId; + _opusEncoder = new OpusEncoder(type); + } + /// /// The of the speakers to play the audio on. /// - public readonly byte ControllerId; + public byte ControllerId { get; } /// /// The queued audio clips. /// Includes the current playing clip. /// - public readonly Queue AudioClipSamples = []; + public Queue AudioClipSamples { get; } = []; /// /// The predicate for determining which players receive audio. @@ -65,56 +82,35 @@ public class AudioTransmitter /// /// If , all authenticated players will receive audio packets. /// - public Func? ValidPlayers = null; + public Func? ValidPlayers { get; set; } = null; /// /// Whether the last queued clip will loop. /// - public bool Looping = false; + public bool Looping { get; set; } = false; /// - /// The position in samples of the current clip. + /// The position in samples of the current clip. /// - public int CurrentPosition = 0; + public int CurrentPosition { get; set; } = 0; /// /// Number of samples in the current clip. /// - public int CurrentSampleCount => currentSamples == EmptyData ? 0 : currentSamples.Length; + public int CurrentSampleCount => _currentSamples == EmptyData ? 0 : _currentSamples.Length; /// /// Whether playback is active and can be stopped or paused. /// - public bool IsPlaying => update.IsRunning && !IsPaused; + public bool IsPlaying => _update.IsRunning && !IsPaused; /// /// Whether playback is paused and can be resumed. /// - public bool IsPaused => update.IsAliveAndPaused; - - private readonly OpusEncoder opusEncoder; - - private CoroutineHandle update; - - private double targetTime = 0.0; - - private bool breakCurrent = false; - - private float[] currentSamples = EmptyData; + public bool IsPaused => _update.IsAliveAndPaused; private bool CanLoop => AudioClipSamples.Count == 0 && Looping; - /// - /// Creates a new audio transmitter for the specified controller. - /// - /// The controller specified by its Id. - /// What kind of audio the encoder should optimise's for. - public AudioTransmitter(byte controllerId, OpusApplicationType type = OpusApplicationType.Audio) - { - ControllerId = controllerId; - opusEncoder = new OpusEncoder(type); - } - /// /// Plays the PCM samples on the current controller. /// @@ -124,17 +120,19 @@ public AudioTransmitter(byte controllerId, OpusApplicationType type = OpusApplic /// The PCM samples. /// Whether to queue the audio if audio is already playing, otherwise overrides the current audio. /// - /// Whether to loop this clip. + /// Whether to loop this clip. /// Loop ends if another clip is played either immediately if not queued or at the end of the loop if next clip was queued. /// public void Play(float[] samples, bool queue, bool loop) { if (samples.IsEmpty()) + { throw new InvalidOperationException($"Audio clip samples must not be empty"); + } if (!queue) { - breakCurrent = true; + _breakCurrent = true; AudioClipSamples.Clear(); CurrentPosition = 0; } @@ -142,8 +140,10 @@ public void Play(float[] samples, bool queue, bool loop) AudioClipSamples.Enqueue(samples); Looping = loop; - if (!update.IsRunning) - update = Timing.RunCoroutine(Transmit(), Segment.Update); + if (!_update.IsRunning) + { + _update = Timing.RunCoroutine(Transmit(), Segment.Update); + } } /// @@ -151,7 +151,7 @@ public void Play(float[] samples, bool queue, bool loop) /// public void Pause() { - update.IsAliveAndPaused = true; + _update.IsAliveAndPaused = true; } /// @@ -159,8 +159,8 @@ public void Pause() /// public void Resume() { - update.IsAliveAndPaused = false; - targetTime = NetworkTime.time; + _update.IsAliveAndPaused = false; + _targetTime = NetworkTime.time; } /// @@ -171,12 +171,16 @@ public void Resume() public void Skip(int count) { if (count == 0) + { return; + } - breakCurrent = true; + _breakCurrent = true; CurrentPosition = 0; for (int i = 1; i < count; i++) + { AudioClipSamples.Dequeue(); + } } /// @@ -184,40 +188,43 @@ public void Skip(int count) /// public void Stop() { - Timing.KillCoroutines(update); + Timing.KillCoroutines(_update); AudioClipSamples.Clear(); CurrentPosition = 0; } private IEnumerator Transmit() { - float root2 = MathF.Sqrt(2.0f); - targetTime = NetworkTime.time; + _targetTime = NetworkTime.time; while (!AudioClipSamples.IsEmpty()) { - currentSamples = AudioClipSamples.Dequeue(); + _currentSamples = AudioClipSamples.Dequeue(); - breakCurrent = false; - while (!breakCurrent && (CanLoop || CurrentPosition < currentSamples.Length)) + _breakCurrent = false; + while (!_breakCurrent && (CanLoop || CurrentPosition < _currentSamples.Length)) { try { - while (targetTime < NetworkTime.time) + while (_targetTime < NetworkTime.time) { int read = 0; while (read != FrameSize) { int remaining = FrameSize - read; - int count = Mathf.Max(Mathf.Min(CurrentPosition + remaining, currentSamples.Length) - CurrentPosition, 0); - Array.Copy(currentSamples, CurrentPosition, TempSampleData, read, count); + int count = Mathf.Max(Mathf.Min(CurrentPosition + remaining, _currentSamples.Length) - CurrentPosition, 0); + Array.Copy(_currentSamples, CurrentPosition, TempSampleData, read, count); if (remaining == count) + { CurrentPosition += count; + } else { CurrentPosition = 0; if (!CanLoop) - currentSamples = AudioClipSamples.IsEmpty() ? EmptyData : AudioClipSamples.Dequeue(); + { + _currentSamples = AudioClipSamples.IsEmpty() ? EmptyData : AudioClipSamples.Dequeue(); + } } read += count; @@ -226,9 +233,11 @@ private IEnumerator Transmit() // Client sided bug causes output to be 3db quieter than expected // so we correct for that here for (int i = 0; i < TempSampleData.Length; i++) - TempSampleData[i] *= root2; + { + TempSampleData[i] *= GainCorrectionFactor; + } - int length = opusEncoder.Encode(TempSampleData, TempEncodedData, FrameSize); + int length = _opusEncoder.Encode(TempSampleData, TempEncodedData, FrameSize); if (length > 2) { AudioMessage msg = new() @@ -239,12 +248,16 @@ private IEnumerator Transmit() }; if (ValidPlayers != null) + { msg.SendToHubsConditionally(x => x.Mode != ClientInstanceMode.Unverified && ValidPlayers.Invoke(Player.Get(x))); + } else + { msg.SendToAuthenticated(); + } } - targetTime += FramePeriod; + _targetTime += FramePeriod; } } catch (Exception ex) diff --git a/LabApi/Features/Console/Logger.cs b/LabApi/Features/Console/Logger.cs index 2b5445e6..e0c59c16 100644 --- a/LabApi/Features/Console/Logger.cs +++ b/LabApi/Features/Console/Logger.cs @@ -30,7 +30,9 @@ public static class Logger public static void Debug(object message, bool canBePrinted = true) { if (!canBePrinted) + { return; + } Raw(FormatLog(message, DebugPrefix, Assembly.GetCallingAssembly()), ConsoleColor.Gray); } diff --git a/LabApi/Features/Enums/DoorName.cs b/LabApi/Features/Enums/DoorName.cs index 21dd9d55..466d70d2 100644 --- a/LabApi/Features/Enums/DoorName.cs +++ b/LabApi/Features/Enums/DoorName.cs @@ -1,47 +1,50 @@ -namespace LabApi.Features.Enums +namespace LabApi.Features.Enums; + +/// +/// Enum type that represents all the door name tags defined in the game. +/// +public enum DoorName { - /// - /// Enum type that represents all the door name tags defined in the game. - /// - public enum DoorName - { - None = 0, - LczPc,// LCZ_CAFE - LczWc,// LCZ_WC - LczCheckpointA,// CHECKPOINT_LCZ_A - LczCheckpointB,// CHECKPOINT_LCZ_B - LczArmory,// LCZ_ARMORY - Lcz173Bottom,// 173_BOTTOM - Lcz173Gate,// 173_GATE - Lcz173Connector,// 173_CONNECTOR - Lcz173Armory,// 173_ARMORY - LczGr18Inner,// GR18_INNER - LczGr18Gate,// GR18 - Lcz914Gate,// 914 - Lcz330,// 330 - Lcz330Chamber,// 330_CHAMBER - Hcz079FirstGate,// 079_FIRST - Hcz079SecondGate,// 079_SECOND - Hcz079Armory,// 079_ARMORY - Hcz096,// 096 - Hcz939Cryo,// 939_CRYO - HczArmory,// HCZ_ARMORY - Hcz049Armory,// 049_ARMORY - HczHidChamber,// HID_CHAMBER - HczHidUpper,// HID_UPPER - HczHidLower,// HID_LOWER - HczNukeArmory,// NUKE_ARMORY - Hcz106Primiary,// 106_PRIMARY - Hcz106Secondary,// 106_SECONDARY - HczCheckpoint,// CHECKPOINT_EZ_HCZ_A - Hcz127Lab, // HCZ_127_LAB - EzIntercom,// INTERCOM - EzGateA,// GATE_A - EzGateB,// GATE_B - SurfaceGate,// SURFACE_GATE - SurfaceNuke,// SURFACE_NUKE - SurfaceEscapePrimary,// ESCAPE_PRIMARY - SurfaceEscapeSecondary,// ESCAPE_SECONDARY - SurfaceEscapeFinal,// ESCAPE_FINAL - } +#pragma warning disable SA1602 // Enumeration items should be documented +#pragma warning disable CS1591 // Missing XML Comment for publicly visible type or member + None = 0, + LczPc, // LCZ_CAFE + LczWc, // LCZ_WC + LczCheckpointA, // CHECKPOINT_LCZ_A + LczCheckpointB, // CHECKPOINT_LCZ_B + LczArmory, // LCZ_ARMORY + Lcz173Bottom, // 173_BOTTOM + Lcz173Gate, // 173_GATE + Lcz173Connector, // 173_CONNECTOR + Lcz173Armory, // 173_ARMORY + LczGr18Inner, // GR18_INNER + LczGr18Gate, // GR18 + Lcz914Gate, // 914 + Lcz330, // 330 + Lcz330Chamber, // 330_CHAMBER + Hcz079FirstGate, // 079_FIRST + Hcz079SecondGate, // 079_SECOND + Hcz079Armory, // 079_ARMORY + Hcz096, // 096 + Hcz939Cryo, // 939_CRYO + HczArmory, // HCZ_ARMORY + Hcz049Armory, // 049_ARMORY + HczHidChamber, // HID_CHAMBER + HczHidUpper, // HID_UPPER + HczHidLower, // HID_LOWER + HczNukeArmory, // NUKE_ARMORY + Hcz106Primiary, // 106_PRIMARY + Hcz106Secondary, // 106_SECONDARY + HczCheckpoint, // CHECKPOINT_EZ_HCZ_A + Hcz127Lab, // HCZ_127_LAB + EzIntercom, // INTERCOM + EzGateA, // GATE_A + EzGateB, // GATE_B + SurfaceGate, // SURFACE_GATE + SurfaceNuke, // SURFACE_NUKE + SurfaceEscapePrimary, // ESCAPE_PRIMARY + SurfaceEscapeSecondary, // ESCAPE_SECONDARY + SurfaceEscapeFinal, // ESCAPE_FINAL +#pragma warning restore SA1602 // Enumeration items should be documented +#pragma warning restore CS1591 // Missing XML Comment for publicly visible type or member } diff --git a/LabApi/Features/Extensions/LinqExtensions.cs b/LabApi/Features/Extensions/LinqExtensions.cs new file mode 100644 index 00000000..d8ccc0b3 --- /dev/null +++ b/LabApi/Features/Extensions/LinqExtensions.cs @@ -0,0 +1,71 @@ +using System; +using System.Collections.Generic; +using System.Linq; + +namespace LabApi.Features.Extensions; + +/// +/// Extensions for Linq. +/// +public static class LinqExtensions +{ + /// + /// Finds smallest value by a specified key. + /// If 2 or more occurrences have the same minimum value then the first one in the collection is returned. + /// + /// The type to compare and select. + /// The value to compare the keys. + /// The enumerable collection. + /// The selection function. + /// Minimum value or if the collection is empty. + public static T? MinBy(this IEnumerable enumerable, Func selectFunc) + where T : class + where TKey : IComparable + { + if (!enumerable.Any()) + { + return null; + } + + T? currentMin = enumerable.First(); + foreach (T member in enumerable) + { + if (selectFunc(member).CompareTo(selectFunc(currentMin)) < 0) + { + currentMin = member; + } + } + + return currentMin; + } + + /// + /// Finds largest value by a specified key. + /// If 2 or more occurrences have the same minimum value then the first one in the collection is returned. + /// + /// The type to compare and select. + /// The value to compare the keys. + /// The enumerable collection. + /// The selection function. + /// Maximum value or if the collection is empty. + public static T? MaxBy(this IEnumerable enumerable, Func selectFunc) + where T : class + where TKey : IComparable + { + if (!enumerable.Any()) + { + return null; + } + + T? currentMin = enumerable.First(); + foreach (T member in enumerable) + { + if (selectFunc(member).CompareTo(selectFunc(currentMin)) > 0) + { + currentMin = member; + } + } + + return currentMin; + } +} diff --git a/LabApi/Features/Extensions/PriorityQueue.cs b/LabApi/Features/Extensions/PriorityQueue.cs new file mode 100644 index 00000000..be989c92 --- /dev/null +++ b/LabApi/Features/Extensions/PriorityQueue.cs @@ -0,0 +1,120 @@ +using System; +using System.Collections.Generic; + +namespace LabApi.Features.Extensions; + +/// +/// Priority queue class. +/// +/// Data type to store in the queue. +public class PriorityQueue +{ + private readonly List<(int, T)> _elements; + + /// + /// Initializes a new instance of the class. + /// + public PriorityQueue() + { + _elements = []; + } + + /// + /// Gets the number of items currently in the queue. + /// + public int Count => _elements.Count; + + /// + /// Adds an item to the priority queue with the specified priority. + /// Smaller numbers indicate higher priority. + /// + /// The item to add. + /// The priority of the item. + public void Enqueue(T item, int priority) + { + ValueTuple newItem = new(priority, item); + _elements.Add(newItem); + HeapifyUp(_elements.Count - 1); + } + + /// + /// Removes and returns the item with the highest priority (smallest priority value) from the queue. + /// + /// The item with the highest priority. + /// Thrown if the queue is empty. + public T Dequeue() + { + if (Count == 0) + { + throw new InvalidOperationException("The queue is empty."); + } + + T bestItem = _elements[0].Item2; + int lastIndex = _elements.Count - 1; + + _elements[0] = _elements[lastIndex]; + _elements.RemoveAt(lastIndex); + + if (Count > 0) + { + HeapifyDown(0); + } + + return bestItem; + } + + /// + /// Clears all items from the queue. + /// + public void Clear() + { + _elements.Clear(); + } + + private void HeapifyUp(int index) + { + int parentIndex = (index - 1) / 2; + while (index > 0 && _elements[index].Item1 < _elements[parentIndex].Item1) + { + Swap(index, parentIndex); + index = parentIndex; + parentIndex = (index - 1) / 2; + } + } + + private void HeapifyDown(int index) + { + int leftChildIndex; + int rightChildIndex; + int smallestChildIndex; + while (true) + { + leftChildIndex = (2 * index) + 1; + rightChildIndex = (2 * index) + 2; + smallestChildIndex = index; + + if (leftChildIndex < Count && _elements[leftChildIndex].Item1 < _elements[smallestChildIndex].Item1) + { + smallestChildIndex = leftChildIndex; + } + + if (rightChildIndex < Count && _elements[rightChildIndex].Item1 < _elements[smallestChildIndex].Item1) + { + smallestChildIndex = rightChildIndex; + } + + if (smallestChildIndex == index) + { + break; + } + + Swap(index, smallestChildIndex); + index = smallestChildIndex; + } + } + + private void Swap(int index1, int index2) + { + (_elements[index1], _elements[index2]) = (_elements[index2], _elements[index1]); + } +} \ No newline at end of file diff --git a/LabApi/Features/Extensions/PriorityQueuePool.cs b/LabApi/Features/Extensions/PriorityQueuePool.cs new file mode 100644 index 00000000..c171c073 --- /dev/null +++ b/LabApi/Features/Extensions/PriorityQueuePool.cs @@ -0,0 +1,37 @@ +using NorthwoodLib.Pools; +using System.Collections.Concurrent; + +namespace LabApi.Features.Extensions; + +/// +/// Pool for . +/// +/// Type of the queue. +public sealed class PriorityQueuePool : IPool> +{ + /// + /// Gets a shared instance. + /// + public static readonly PriorityQueuePool Shared = new(); + + private readonly ConcurrentQueue> _pool = new(); + + /// + /// Gives a pooled or creates a new one if the pool is empty. + /// + /// A instance from the pool. + public PriorityQueue Rent() + { + return _pool.TryDequeue(out PriorityQueue set) ? set : new PriorityQueue(); + } + + /// + /// Returns a to the pool for reuse. + /// + /// The to return to the pool. + public void Return(PriorityQueue queue) + { + queue.Clear(); + _pool.Enqueue(queue); + } +} diff --git a/LabApi/Features/Extensions/RoleExtensions.cs b/LabApi/Features/Extensions/RoleExtensions.cs index d7cf9ed1..a3ec6e5f 100644 --- a/LabApi/Features/Extensions/RoleExtensions.cs +++ b/LabApi/Features/Extensions/RoleExtensions.cs @@ -1,4 +1,9 @@ -using PlayerRoles; +using System.Collections.Generic; +using PlayerRoles; +using System.Diagnostics.CodeAnalysis; +using InventorySystem; +using InventorySystem.Configs; +using PlayerRoles.FirstPersonControl; using UnityEngine; namespace LabApi.Features.Extensions; @@ -8,20 +13,58 @@ namespace LabApi.Features.Extensions; /// public static class RoleExtensions { + private static readonly InventoryRoleInfo EmptyInventoryInfo = new([], []); // prevent creating this multiple time + /// /// Gets the from a . /// /// The . /// The . public static PlayerRoleBase GetRoleBase(this RoleTypeId roleType) => PlayerRoleLoader.TryGetRoleTemplate(roleType, out PlayerRoleBase role) ? role : null!; - + + /// + /// Tries to get a role base from a . + /// + /// The to get base of. + /// The found. + /// The . + /// The role base found, else null. + public static bool TryGetRoleBase(this RoleTypeId roleTypeId, [NotNullWhen(true)] out T? role) => PlayerRoleLoader.TryGetRoleTemplate(roleTypeId, out role); + /// /// Gets the human-readable version of a 's name. /// /// The . /// The name of the role. public static string GetFullName(this RoleTypeId roleType) => roleType.GetRoleBase().RoleName; - + + /// + /// Tries to get a random spawn point from a . + /// + /// The role to get spawn from. + /// The position found. + /// The rotation found. + /// Whether a SpawnPoint was found. + public static bool TryGetRandomSpawnPoint(this RoleTypeId role, out Vector3 position, out float horizontalRotation) + { + if (TryGetRoleBase(role, out IFpcRole? fpcRole)) + { + return fpcRole.SpawnpointHandler.TryGetSpawnpoint(out position, out horizontalRotation); + } + + position = Vector3.zero; + horizontalRotation = 0f; + return false; + } + + /// + /// Gets the inventory of the specified . + /// + /// The to get inventory of. + /// The found. + public static InventoryRoleInfo GetInventory(this RoleTypeId roleTypeId) + => StartingInventories.DefinedInventories.GetValueOrDefault(roleTypeId, EmptyInventoryInfo); + /// /// Checks if the role is an SCP role. /// @@ -62,5 +105,5 @@ public static class RoleExtensions /// /// The . /// A boolean which is true when the role is a civilian role. - public static bool IsCivilian(this RoleTypeId roleType) => roleType == RoleTypeId.ClassD || roleType == RoleTypeId.Scientist; + public static bool IsCivilian(this RoleTypeId roleType) => roleType is RoleTypeId.ClassD or RoleTypeId.Scientist; } \ No newline at end of file diff --git a/LabApi/Features/Interfaces/IScp914ItemProcessor.cs b/LabApi/Features/Interfaces/IScp914ItemProcessor.cs index ce9f8f9f..9e7f4c83 100644 --- a/LabApi/Features/Interfaces/IScp914ItemProcessor.cs +++ b/LabApi/Features/Interfaces/IScp914ItemProcessor.cs @@ -1,5 +1,6 @@ using LabApi.Features.Wrappers; using Scp914; +using UnityEngine; namespace LabApi.Features.Interfaces; @@ -8,6 +9,11 @@ namespace LabApi.Features.Interfaces; /// public interface IScp914ItemProcessor { + /// + /// The amount of world space position that needs to be added to move a pickup item from the input chamber to the output chamber. + /// + public static Vector3 MoveVector => Scp914Controller.MoveVector; + /// /// Whether to use the for inventory items and skip using . /// @@ -28,6 +34,9 @@ public interface IScp914ItemProcessor /// /// Called for each pickup in the intake chamber if the allows so. /// + /// + /// Add to the pickups world position to move pickup from the input chamber to the output. + /// /// The used for this upgrade. /// The to upgrade. /// The upgrade result. diff --git a/LabApi/Features/LabApiProperties.cs b/LabApi/Features/LabApiProperties.cs index b35c6abd..3c7f1895 100644 --- a/LabApi/Features/LabApiProperties.cs +++ b/LabApi/Features/LabApiProperties.cs @@ -29,7 +29,9 @@ private static string GetCompiledVersion() AssemblyInformationalVersionAttribute att = assembly.GetCustomAttribute(); if (att == null) + { return defaultVersion; + } string version = att.InformationalVersion ?? defaultVersion; int index = version.IndexOf('+'); diff --git a/LabApi/Features/Permissions/PermissionsExtensions.cs b/LabApi/Features/Permissions/PermissionsExtensions.cs index cc65ca67..dec1782b 100644 --- a/LabApi/Features/Permissions/PermissionsExtensions.cs +++ b/LabApi/Features/Permissions/PermissionsExtensions.cs @@ -1,8 +1,8 @@ -using System; -using System.Collections.Generic; using CommandSystem; using LabApi.Features.Wrappers; using RemoteAdmin; +using System; +using System.Collections.Generic; namespace LabApi.Features.Permissions; @@ -13,11 +13,11 @@ public static class PermissionsExtensions { /// public static Dictionary GetPermissionsByProvider(this ICommandSender sender) => - Player.Get(sender)?.GetPermissionsByProvider() ?? new Dictionary(); + Player.Get(sender)?.GetPermissionsByProvider() ?? []; /// public static string[] GetPermissions(this ICommandSender sender) => - Player.Get(sender)?.GetPermissions() ?? Array.Empty(); + Player.Get(sender)?.GetPermissions() ?? []; /// public static bool HasPermissions(this ICommandSender sender, params string[] permissions) => diff --git a/LabApi/Features/Permissions/PermissionsManager.cs b/LabApi/Features/Permissions/PermissionsManager.cs index b21cb91b..58cefce7 100644 --- a/LabApi/Features/Permissions/PermissionsManager.cs +++ b/LabApi/Features/Permissions/PermissionsManager.cs @@ -1,8 +1,8 @@ +using LabApi.Features.Console; +using LabApi.Features.Wrappers; using System; using System.Collections.Generic; using System.Linq; -using LabApi.Features.Console; -using LabApi.Features.Wrappers; namespace LabApi.Features.Permissions; @@ -16,13 +16,14 @@ public static class PermissionsManager /// /// Internal dictionary to store the registered permission providers. /// - private static readonly Dictionary PermissionProviders = new(); + private static readonly Dictionary PermissionProviders = []; /// /// Registers the given . /// /// The type of the permission provider to register. - public static void RegisterProvider() where T : IPermissionsProvider, new() + public static void RegisterProvider() + where T : IPermissionsProvider, new() { if (PermissionProviders.ContainsKey(typeof(T))) { @@ -43,10 +44,13 @@ public static class PermissionsManager /// Unregisters the given . /// /// The type of the permission provider to unregister. - public static void UnregisterProvider() where T : IPermissionsProvider, new() + public static void UnregisterProvider() + where T : IPermissionsProvider, new() { if (PermissionProviders.Remove(typeof(T))) + { return; + } Logger.Warn($"{LoggerPrefix} Failed to unregister the permission provider of type {typeof(T).FullName}. It is not registered."); } @@ -56,10 +60,13 @@ public static class PermissionsManager /// /// The type of the permission provider to retrieve. /// The registered of the given type ; otherwise, null. - public static IPermissionsProvider? GetProvider() where T : IPermissionsProvider, new() + public static IPermissionsProvider? GetProvider() + where T : IPermissionsProvider, new() { if (PermissionProviders.TryGetValue(typeof(T), out IPermissionsProvider provider)) + { return provider; + } Logger.Warn($"{LoggerPrefix} The permission provider of type {typeof(T).FullName} is not registered."); return null; diff --git a/LabApi/Features/Permissions/Providers/DefaultPermissionsProvider.cs b/LabApi/Features/Permissions/Providers/DefaultPermissionsProvider.cs index 4a51a584..0b49ac83 100644 --- a/LabApi/Features/Permissions/Providers/DefaultPermissionsProvider.cs +++ b/LabApi/Features/Permissions/Providers/DefaultPermissionsProvider.cs @@ -1,12 +1,12 @@ -using System; -using System.Collections.Generic; -using System.IO; -using System.Linq; using LabApi.Features.Console; using LabApi.Features.Wrappers; using LabApi.Loader.Features.Paths; using NorthwoodLib.Pools; using Serialization; +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; namespace LabApi.Features.Permissions.Providers; @@ -20,7 +20,7 @@ public class DefaultPermissionsProvider : IPermissionsProvider private const string PermissionsFileName = "permissions.yml"; private readonly FileInfo _permissions; - private Dictionary _permissionsDictionary = new(); + private Dictionary _permissionsDictionary = []; /// /// Creates a new instance of the class. @@ -86,7 +86,7 @@ public bool HasAnyPermission(Player player, params string[] permissions) public void AddPermissions(Player player, params string[] permissions) { PermissionGroup group = GetPlayerGroup(player); - group.Permissions = group.Permissions.Concat(permissions).ToArray(); + group.Permissions = [.. group.Permissions, .. permissions]; ReloadPermissions(); SavePermissions(); } @@ -100,6 +100,9 @@ public void RemovePermissions(Player player, params string[] permissions) SavePermissions(); } + /// + void IPermissionsProvider.ReloadPermissions() => ReloadPermissions(); + private PermissionGroup GetPlayerGroup(Player player) => _permissionsDictionary.GetValueOrDefault(player.PermissionsGroupName ?? "default") ?? PermissionGroup.Default; private string[] GetPermissions(PermissionGroup group) @@ -112,22 +115,28 @@ private string[] GetPermissions(PermissionGroup group) foreach (string inheritedGroup in group.InheritedGroups) { if (!_permissionsDictionary.TryGetValue(inheritedGroup, out PermissionGroup inherited)) + { continue; + } permissions.AddRange(GetPermissions(inherited)); } - return permissions.ToArray(); + return [.. permissions]; } private bool HasPermission(PermissionGroup group, string permission) { if (group.IsRoot) + { return true; - + } + // We do first check if the group has the permission. if (group.Permissions.Contains(permission)) + { return true; + } if (permission.Contains(".")) { @@ -135,17 +144,23 @@ private bool HasPermission(PermissionGroup group, string permission) string perm = permission[..index]; if (group.SpecialPermissionsSuperset.Contains(perm + ".*")) + { return true; + } } // Then we check if the group has the permission from the inherited groups. foreach (string inheritedGroup in group.InheritedGroups) { if (!_permissionsDictionary.TryGetValue(inheritedGroup, out PermissionGroup inherited)) + { continue; + } if (HasPermission(inherited, permission)) + { return true; + } } return false; @@ -157,8 +172,6 @@ private void LoadDefaultPermissions() ReloadPermissions(); } - void IPermissionsProvider.ReloadPermissions() => ReloadPermissions(); - private void ReloadPermissions() { // We clear the special permissions and fill them again. @@ -170,12 +183,15 @@ private void ReloadPermissions() if (permission == ".*") { permissionsGroup.IsRoot = true; + // We don't have to continue. break; } - + if (!permission.Contains(".*")) + { continue; + } int index = permission.LastIndexOf(".", StringComparison.Ordinal); string perm = permission[..index]; diff --git a/LabApi/Features/Permissions/Providers/PermissionGroup.cs b/LabApi/Features/Permissions/Providers/PermissionGroup.cs index dcb80acb..875e0806 100644 --- a/LabApi/Features/Permissions/Providers/PermissionGroup.cs +++ b/LabApi/Features/Permissions/Providers/PermissionGroup.cs @@ -1,4 +1,3 @@ -using System; using System.Collections.Generic; using YamlDotNet.Serialization; @@ -9,20 +8,6 @@ namespace LabApi.Features.Permissions.Providers; /// public class PermissionGroup { - /// - /// Constructor for deserialization. - /// - public PermissionGroup() : this([], []) {} - - /// - /// Represents a group of permissions. They are linked to RA user groups. - /// - public PermissionGroup(string[] inheritedGroups, string[] permissions) - { - InheritedGroups = inheritedGroups; - Permissions = permissions; - } - /// /// Gets the default permission group. /// @@ -37,13 +22,32 @@ public static Dictionary DefaultPermissionGroups { Dictionary groups = new() { - ["default"] = Default + ["default"] = Default, }; return groups; } } + /// + /// Constructor for deserialization. + /// + public PermissionGroup() + : this([], []) + { + } + + /// + /// Represents a group of permissions. They are linked to RA user groups. + /// + /// Array of groups that should be inherited. + /// Array of permissions this group should have. + public PermissionGroup(string[] inheritedGroups, string[] permissions) + { + InheritedGroups = inheritedGroups; + Permissions = permissions; + } + /// /// The inherited groups of the group. /// diff --git a/LabApi/Features/Stores/CustomDataStore.cs b/LabApi/Features/Stores/CustomDataStore.cs index 8677c738..90b4d3d4 100644 --- a/LabApi/Features/Stores/CustomDataStore.cs +++ b/LabApi/Features/Stores/CustomDataStore.cs @@ -1,8 +1,8 @@ +using LabApi.Features.Wrappers; +using NorthwoodLib.Pools; using System; using System.Collections.Generic; using System.Linq; -using LabApi.Features.Wrappers; -using NorthwoodLib.Pools; namespace LabApi.Features.Stores; @@ -11,22 +11,7 @@ namespace LabApi.Features.Stores; /// public abstract class CustomDataStore { - private static readonly Dictionary> StoreInstances = new (); - - /// - /// Gets the that this instance is associated with. - /// - public Player Owner { get; internal set; } - - /// - /// Initializes a new instance of the class. - /// - /// The that this instance is associated with. - protected CustomDataStore(Player owner) - { - Owner = owner; - InternalOnInstanceCreated(); - } + private static readonly Dictionary> StoreInstances = []; /// /// Gets the for the specified , or creates a new one if it doesn't exist. @@ -40,16 +25,20 @@ public static TStore GetOrAdd(Player player) Type type = typeof(TStore); if (!CustomDataStoreManager.IsRegistered()) + { CustomDataStoreManager.RegisterStore(); + } if (!StoreInstances.TryGetValue(type, out Dictionary? playerStores)) { - playerStores = new Dictionary(); + playerStores = []; StoreInstances[type] = playerStores; } if (playerStores.TryGetValue(player, out CustomDataStore? store)) + { return (TStore)store; + } store = (TStore)Activator.CreateInstance(type, player); playerStores[player] = store; @@ -57,16 +46,6 @@ public static TStore GetOrAdd(Player player) return (TStore)store; } - /// - /// Called when a new instance of the is created. - /// - protected virtual void OnInstanceCreated() { } - - /// - /// Called when an instance of the is going to be destroyed. - /// - protected virtual void OnInstanceDestroyed() { } - /// /// Destroys the for the specified . /// @@ -76,10 +55,14 @@ internal static void Destroy(Player player) where TStore : CustomDataStore { if (!StoreInstances.TryGetValue(typeof(TStore), out Dictionary? playerStores)) + { return; + } if (!playerStores.TryGetValue(player, out CustomDataStore? store)) + { return; + } store.Destroy(); } @@ -90,47 +73,54 @@ internal static void Destroy(Player player) /// The type of the . internal static void DestroyAll() { - List? storesToRemove = ListPool.Shared.Rent(StoreInstances.SelectMany(entry => - entry.Value.Where(playerStore => playerStore.Value.GetType() == typeof(TStore)).Select(playerStore => playerStore.Value))); + List? storesToRemove = ListPool.Shared.Rent(StoreInstances.SelectMany(static entry => + entry.Value.Where(static playerStore => playerStore.Value.GetType() == typeof(TStore)).Select(playerStore => playerStore.Value))); foreach (CustomDataStore? store in storesToRemove) + { store.Destroy(); + } ListPool.Shared.Return(storesToRemove); } + /// + /// Initializes a new instance of the class. + /// + /// The that this instance is associated with. + protected CustomDataStore(Player owner) + { + Owner = owner; + InternalOnInstanceCreated(); + } + + /// + /// Gets the that this instance is associated with. + /// + public Player Owner { get; internal set; } + /// /// Destroys this instance of the . /// internal void Destroy() { OnInstanceDestroyed(); - StoreInstances[this.GetType()].Remove(Owner); + StoreInstances[GetType()].Remove(Owner); } - private void InternalOnInstanceCreated() => OnInstanceCreated(); -} - -/// -/// Represents a Custom Data Store that plugins can use to store data with a player. -/// -/// The type of the . -public abstract class CustomDataStore : CustomDataStore - where TStore : CustomDataStore -{ /// - /// Initializes a new instance of the class. + /// Called when a new instance of the is created. /// - /// The that this instance is associated with. - protected CustomDataStore(Player owner) - : base(owner) + protected virtual void OnInstanceCreated() { } /// - /// Gets the for the specified . + /// Called when an instance of the is going to be destroyed. /// - /// The to get the for. - /// The for the specified . - public static TStore Get(Player player) => GetOrAdd(player); + protected virtual void OnInstanceDestroyed() + { + } + + private void InternalOnInstanceCreated() => OnInstanceCreated(); } \ No newline at end of file diff --git a/LabApi/Features/Stores/CustomDataStoreManager.cs b/LabApi/Features/Stores/CustomDataStoreManager.cs index 57add4ba..d882830a 100644 --- a/LabApi/Features/Stores/CustomDataStoreManager.cs +++ b/LabApi/Features/Stores/CustomDataStoreManager.cs @@ -1,7 +1,7 @@ +using LabApi.Features.Wrappers; using System; using System.Collections.Generic; using System.Reflection; -using LabApi.Features.Wrappers; namespace LabApi.Features.Stores; @@ -10,10 +10,10 @@ namespace LabApi.Features.Stores; /// public static class CustomDataStoreManager { - private static readonly List RegisteredStores = new (); - private static readonly Dictionary GetOrAddMethods = new (); - private static readonly Dictionary DestroyMethods = new (); - private static readonly Dictionary DestroyAllMethods = new (); + private static readonly List RegisteredStores = []; + private static readonly Dictionary GetOrAddMethods = []; + private static readonly Dictionary DestroyMethods = []; + private static readonly Dictionary DestroyAllMethods = []; /// /// Registers a custom data store. @@ -24,25 +24,34 @@ public static bool RegisterStore() where T : CustomDataStore { Type type = typeof(T); - if (RegisteredStores.Contains(type)) return false; + if (RegisteredStores.Contains(type)) + { + return false; + } MethodInfo? getOrAddMethod = typeof(CustomDataStore).GetMethod(nameof(CustomDataStore.GetOrAdd), BindingFlags.Static | BindingFlags.NonPublic | BindingFlags.Public); if (getOrAddMethod == null) + { return false; + } getOrAddMethod = getOrAddMethod.MakeGenericMethod(type); GetOrAddMethods.Add(type, getOrAddMethod); MethodInfo? destroyMethod = typeof(CustomDataStore).GetMethod(nameof(CustomDataStore.Destroy), BindingFlags.Static | BindingFlags.NonPublic | BindingFlags.Public); if (destroyMethod == null) + { return false; + } destroyMethod = destroyMethod.MakeGenericMethod(type); DestroyMethods.Add(type, destroyMethod); MethodInfo? destroyAllMethod = typeof(CustomDataStore).GetMethod(nameof(CustomDataStore.DestroyAll), BindingFlags.Static | BindingFlags.NonPublic | BindingFlags.Public); if (destroyAllMethod == null) + { return false; + } destroyAllMethod = destroyAllMethod.MakeGenericMethod(type); DestroyAllMethods.Add(type, destroyAllMethod); @@ -60,9 +69,11 @@ public static void UnregisterStore() where T : CustomDataStore { Type type = typeof(T); - + if (DestroyAllMethods.TryGetValue(type, out MethodInfo? method)) + { method.Invoke(null, null); + } DestroyAllMethods.Remove(type); RegisteredStores.Remove(type); @@ -70,19 +81,41 @@ public static void UnregisterStore() DestroyMethods.Remove(type); } + /// + /// Method used to initialize stores when a new player joins the server. + /// + /// The player added to the game. internal static void AddPlayer(Player player) { foreach (Type? storeType in RegisteredStores) - GetOrAddMethods[storeType].Invoke(null, new object[] { player }); + { + GetOrAddMethods[storeType].Invoke(null, [player]); + } } - internal static void RemovePlayer(Player player) + /// + /// Method used to destroy stores when an existing player leaves the server. + /// + /// The player removed from the game. + internal static void RemovePlayer(Player player) { foreach (Type? storeType in RegisteredStores) - DestroyMethods[storeType].Invoke(null, new object[] { player }); + { + DestroyMethods[storeType].Invoke(null, [player]); + } } + /// + /// Whether the store type had been registered. + /// + /// The of the store. + /// if registered; otherwise . internal static bool IsRegistered(Type type) => RegisteredStores.Contains(type); + /// + /// Whether the store type had been registered. + /// + /// The stores type. + /// if registered; otherwise . internal static bool IsRegistered() => IsRegistered(typeof(T)); } \ No newline at end of file diff --git a/LabApi/Features/Stores/CustomDataStore{TStore}.cs b/LabApi/Features/Stores/CustomDataStore{TStore}.cs new file mode 100644 index 00000000..4daa39a4 --- /dev/null +++ b/LabApi/Features/Stores/CustomDataStore{TStore}.cs @@ -0,0 +1,27 @@ +using LabApi.Features.Wrappers; + +namespace LabApi.Features.Stores; + +/// +/// Represents a Custom Data Store that plugins can use to store data with a player. +/// +/// The type of the . +public abstract class CustomDataStore : CustomDataStore + where TStore : CustomDataStore +{ + /// + /// Gets the for the specified . + /// + /// The to get the for. + /// The for the specified . + public static TStore Get(Player player) => GetOrAdd(player); + + /// + /// Initializes a new instance of the class. + /// + /// The that this instance is associated with. + protected CustomDataStore(Player owner) + : base(owner) + { + } +} diff --git a/LabApi/Features/Wrappers/AdminToys/AdminToy.cs b/LabApi/Features/Wrappers/AdminToys/AdminToy.cs index 507168bd..7e2c8e77 100644 --- a/LabApi/Features/Wrappers/AdminToys/AdminToy.cs +++ b/LabApi/Features/Wrappers/AdminToys/AdminToy.cs @@ -13,6 +13,49 @@ namespace LabApi.Features.Wrappers; /// public class AdminToy { + /// + /// Contains all the handlers for constructing wrappers for the associated base game types. + /// + private static readonly Dictionary> _typeWrappers = []; + + /// + /// Contains all the cached admin toys, accessible through their . + /// + public static Dictionary Dictionary { get; } = []; + + /// + /// A reference to all instances of . + /// + public static IReadOnlyCollection List => Dictionary.Values; + + /// + /// Gets the admin toy wrapper from the or creates a new one if it doesn't exist and the provided was not . + /// + /// The of the admin toy. + /// The requested admin toy or . + [return: NotNullIfNotNull(nameof(adminToyBase))] + public static AdminToy? Get(AdminToyBase? adminToyBase) + { + if (adminToyBase == null) + { + return null; + } + + return Dictionary.TryGetValue(adminToyBase, out AdminToy item) ? item : CreateAdminToyWrapper(adminToyBase); + } + + /// + /// Tries to get the admin toy wrapper from the . + /// + /// The of the admin toy. + /// The requested admin toy. + /// True if the admin toy exists, otherwise . + public static bool TryGet(AdminToyBase? adminToyBase, [NotNullWhen(true)] out AdminToy? adminToy) + { + adminToy = Get(adminToyBase); + return adminToy != null; + } + /// /// Initializes the class. /// @@ -30,38 +73,131 @@ internal static void Initialize() Register(static x => new CameraToy(x)); Register(static x => new CapybaraToy(x)); Register(static x => new TextToy(x)); + Register(static x => new WaypointToy(x)); } /// - /// Contains all the handlers for constructing wrappers for the associated base game types. + /// Instantiates a new base game admin toy object. /// - private static readonly Dictionary> typeWrappers = []; + /// The base game admin toy type. + /// The initial local position. + /// The initial local rotation. + /// The initial local scale. + /// The parent transform. + /// The instantiated admin toy. + protected static T Create(Vector3 position, Quaternion rotation, Vector3 scale, Transform? parent) + where T : AdminToyBase + { + if (PrefabCache.Prefab == null) + { + T? found = null; + foreach (GameObject prefab in NetworkClient.prefabs.Values) + { + if (prefab.TryGetComponent(out found)) + { + break; + } + } + + if (found == null) + { + throw new InvalidOperationException($"No prefab in NetworkClient.prefabs has component type {typeof(T)}"); + } + + PrefabCache.Prefab = found; + } + + T instance = UnityEngine.Object.Instantiate(PrefabCache.Prefab, parent); + instance.transform.localPosition = position; + instance.transform.localRotation = rotation; + instance.transform.localScale = scale; + return instance; + } /// - /// Contains all the cached admin toys, accessible through their . + /// Creates a new wrapper from the base admin toy object. /// - public static Dictionary Dictionary { get; } = []; + /// The base object. + /// The newly created wrapper. + protected static AdminToy CreateAdminToyWrapper(AdminToyBase adminToyBase) + { + if (!_typeWrappers.TryGetValue(adminToyBase.GetType(), out Func handler)) + { + Console.Logger.InternalWarn($"Backing up to the default AdminToy constructor. Missing constructor handler for type {adminToyBase.GetType()}"); + return new AdminToy(adminToyBase); + } + + AdminToy? wrapper = handler.Invoke(adminToyBase); + if (wrapper == null) + { + Console.Logger.InternalWarn($"Backing up to the default AdminToy constructor. A handler returned null for type {adminToyBase.GetType()}"); + return new AdminToy(adminToyBase); + } + + return wrapper; + } /// - /// A reference to all instances of . + /// A private method to handle the creation of new admin toys in the server. /// - public static IReadOnlyCollection List => Dictionary.Values; + /// The created instance. + private static void AddAdminToy(AdminToyBase adminToyBase) + { + try + { + if (!Dictionary.ContainsKey(adminToyBase)) + { + _ = CreateAdminToyWrapper(adminToyBase); + } + } + catch (Exception e) + { + Console.Logger.InternalError($"Failed to handle admin toy creation with error: {e}"); + } + } /// - /// A protected constructor to prevent external instantiation. + /// A private method to handle the removal of admin toys from the server. /// - /// The base object. - protected AdminToy(AdminToyBase adminToyBase) + /// The to be destroyed instance. + private static void RemoveAdminToy(AdminToyBase adminToyBase) { - Dictionary.Add(adminToyBase, this); - Base = adminToyBase; + try + { + if (Dictionary.Remove(adminToyBase, out AdminToy adminToy)) + { + adminToy.OnRemove(); + } + } + catch (Exception e) + { + Console.Logger.InternalError($"Failed to handle admin toy destruction with error: {e}"); + } } /// - /// An internal method to remove itself from the cache when the base object is destroyed. + /// A private method to handle the addition of wrapper handlers. /// - internal virtual void OnRemove() + /// The derived base game type to handle. + /// A handler to construct the wrapper with the base game instance. + private static void Register(Func constructor) + where T : AdminToyBase { + _typeWrappers.Add(typeof(T), x => constructor((T)x)); + } + + /// + /// A protected constructor to prevent external instantiation. + /// + /// The base object. + protected AdminToy(AdminToyBase adminToyBase) + { + Base = adminToyBase; + + if (CanCache) + { + Dictionary.Add(adminToyBase, this); + } } /// @@ -92,9 +228,9 @@ internal virtual void OnRemove() /// Position is relative to its parent if it has one, otherwise its the world position. /// /// - /// If is true client wont update its position. + /// If is client wont update its position. /// - public Vector3 Position + public virtual Vector3 Position { get => Transform.localPosition; set => Transform.localPosition = value; @@ -105,9 +241,9 @@ public Vector3 Position /// Rotation is relative to its parent if it has one, otherwise its the world rotation. /// /// - /// If is true client wont update its rotation. + /// If is client wont update its rotation. /// - public Quaternion Rotation + public virtual Quaternion Rotation { get => Transform.localRotation; set => Transform.localRotation = value; @@ -118,9 +254,9 @@ public Quaternion Rotation /// Scale is relative to its parent if it has one, otherwise its the world scale. /// /// - /// If is true client wont update its scale. + /// If is client wont update its scale. /// - public Vector3 Scale + public virtual Vector3 Scale { get => Transform.localScale; set => Transform.localScale = value; @@ -132,9 +268,9 @@ public Vector3 Scale /// /// If the parent object contains a component and has been the parent is synced with the client. /// - /// Can be used even if is true. + /// Can be used even if is . /// When changing parent the toys relative , and are retained. - /// Note that if the parent has called on it this object automatically has called on itself. + /// Note that if the parent has called on it this object automatically has called on itself. /// To prevent destruction make sure you unparent it before that happens. /// /// @@ -162,11 +298,11 @@ public byte MovementSmoothing /// /// Gets or sets whether the admin toy is static. /// This should be enabled on as many toys possible to increase performance. - /// Static is only applies to the local transformations so parenting to something that moves will still causes it to move while retaining the performance boost. + /// Static is only applies to the local transformations so parenting to something that moves will still cause it to move while retaining the performance boost. /// /// /// A static admin toy will not process , or on both server and client drastically increasing performance. - /// can still be used even if static is true. + /// can still be used even if static is . /// public bool IsStatic { @@ -185,11 +321,16 @@ public float SyncInterval set => Base.syncInterval = value; } + /// + /// Whether to cache this wrapper. + /// + protected bool CanCache => !IsDestroyed && Base.isActiveAndEnabled; + /// /// Spawns the toy on the client. /// /// - /// Spawn wont cascade to children toy objects, so if they are not spawned you have to call spawn on all of them. + /// Spawn won't cascade to children toy objects, so if they are not spawned you have to call spawn on all of them. /// public void Spawn() => NetworkServer.Spawn(GameObject); @@ -202,140 +343,24 @@ public float SyncInterval public void Destroy() => NetworkServer.Destroy(GameObject); /// - /// Instantiates a new base game admin toy object. - /// - /// The base game admin toy type. - /// The initial local position. - /// The initial local rotation. - /// The initial local scale. - /// The parent transform. - /// The instantiated admin toy. - protected static T Create(Vector3 position, Quaternion rotation, Vector3 scale, Transform? parent) where T : AdminToyBase - { - if (PrefabCache.prefab == null) - { - T? found = null; - foreach (GameObject prefab in NetworkClient.prefabs.Values) - { - if (prefab.TryGetComponent(out found)) - break; - } - - if (found == null) - throw new InvalidOperationException($"No prefab in NetworkClient.prefabs has component type {typeof(T)}"); - - PrefabCache.prefab = found; - } - - T instance = UnityEngine.Object.Instantiate(PrefabCache.prefab, parent); - instance.transform.localPosition = position; - instance.transform.localRotation = rotation; - instance.transform.localScale = scale; - return instance; - } - - /// - /// Gets the admin toy wrapper from the or creates a new one if it doesn't exist and the provided was not . - /// - /// The of the admin toy. - /// The requested admin toy or . - [return: NotNullIfNotNull(nameof(adminToyBase))] - public static AdminToy? Get(AdminToyBase? adminToyBase) - { - if (adminToyBase == null) - return null; - - return Dictionary.TryGetValue(adminToyBase, out AdminToy item) ? item : CreateAdminToyWrapper(adminToyBase); - } - - /// - /// Tries to get the admin toy wrapper from the . - /// - /// The of the admin toy. - /// The requested admin toy. - /// True if the admin toy exists, otherwise . - public static bool TryGet(AdminToyBase? adminToyBase, [NotNullWhen(true)] out AdminToy? adminToy) - { - adminToy = Get(adminToyBase); - return adminToy != null; - } - - /// - /// Creates a new wrapper from the base admin toy object. - /// - /// The base object. - /// The newly created wrapper. - protected static AdminToy CreateAdminToyWrapper(AdminToyBase adminToyBase) - { - if (!typeWrappers.TryGetValue(adminToyBase.GetType(), out Func handler)) - { - Console.Logger.InternalWarn($"Backing up to the default AdminToy constructor. Missing constructor handler for type {adminToyBase.GetType()}"); - return new AdminToy(adminToyBase); - } - - AdminToy? wrapper = handler.Invoke(adminToyBase); - if (wrapper == null) - { - Console.Logger.InternalWarn($"Backing up to the default AdminToy constructor. A handler returned null for type {adminToyBase.GetType()}"); - return new AdminToy(adminToyBase); - } - - return wrapper ?? new AdminToy(adminToyBase); - } - - /// - /// A private method to handle the creation of new admin toys in the server. - /// - /// The created instance. - private static void AddAdminToy(AdminToyBase adminToyBase) - { - try - { - if (!Dictionary.ContainsKey(adminToyBase)) - _ = CreateAdminToyWrapper(adminToyBase); - } - catch (Exception e) - { - Console.Logger.InternalError($"Failed to handle admin toy creation with error: {e}"); - } - } - - /// - /// A private method to handle the removal of admin toys from the server. + /// An internal method to remove itself from the cache when the base object is destroyed. /// - /// The to be destroyed instance. - private static void RemoveAdminToy(AdminToyBase adminToyBase) + internal virtual void OnRemove() { - try - { - - if (Dictionary.TryGetValue(adminToyBase, out AdminToy adminToy)) - { - Dictionary.Remove(adminToyBase); - adminToy.OnRemove(); - } - } - catch (Exception e) - { - Console.Logger.InternalError($"Failed to handle admin toy destruction with error: {e}"); - } } +#pragma warning disable SA1204 // Static elements should appear before instance elements /// - /// A private method to handle the addition of wrapper handlers. + /// Static prefab cache used to speed up prefab search. /// - /// The derived base game type to handle. - /// A handler to construct the wrapper with the base game instance. - private static void Register(Func constructor) where T : AdminToyBase - { - typeWrappers.Add(typeof(T), x => constructor((T)x)); - } - - private static class PrefabCache where T : AdminToyBase + /// The base game component type of the prefab. + internal static class PrefabCache + where T : NetworkBehaviour { /// /// Cached prefab instance for type T. /// - public static T? prefab = null; + public static T? Prefab { get; set; } = null; } +#pragma warning restore SA1204 // Static elements should appear before instance elements } diff --git a/LabApi/Features/Wrappers/AdminToys/CameraToy.cs b/LabApi/Features/Wrappers/AdminToys/CameraToy.cs index 6e996156..66050724 100644 --- a/LabApi/Features/Wrappers/AdminToys/CameraToy.cs +++ b/LabApi/Features/Wrappers/AdminToys/CameraToy.cs @@ -13,12 +13,73 @@ public class CameraToy : AdminToy /// /// Contains all the camera toys, accessible through their . /// - public new static Dictionary Dictionary { get; } = []; + public static new Dictionary Dictionary { get; } = []; /// /// A reference to all instances of . /// - public new static IReadOnlyCollection List => Dictionary.Values; + public static new IReadOnlyCollection List => Dictionary.Values; + + /// + public static CameraToy Create(Transform? parent = null, bool networkSpawn = true) + => Create(Vector3.zero, parent, networkSpawn); + + /// + public static CameraToy Create(Vector3 position, Transform? parent = null, bool networkSpawn = true) + => Create(position, Quaternion.identity, parent, networkSpawn); + + /// + public static CameraToy Create(Vector3 position, Quaternion rotation, Transform? parent = null, bool networkSpawn = true) + => Create(position, rotation, Vector3.one, parent, networkSpawn); + + /// + /// Creates a new camera toy. + /// + /// The initial local position. + /// The initial local rotation. + /// The initial local scale. + /// The parent transform. + /// Whether to spawn the toy on the client. + /// The created camera toy. + public static CameraToy Create(Vector3 position, Quaternion rotation, Vector3 scale, Transform? parent = null, bool networkSpawn = true) + { + CameraToy toy = Get(Create(position, rotation, scale, parent)); + + if (networkSpawn) + { + toy.Spawn(); + } + + return toy; + } + + /// + /// Gets the camera toy wrapper from the or creates a new one if it doesn't exist and the provided was not . + /// + /// The of the camera toy. + /// The requested camera toy or . + [return: NotNullIfNotNull(nameof(baseCameraToy))] + public static CameraToy? Get(Scp079CameraToy? baseCameraToy) + { + if (baseCameraToy == null) + { + return null; + } + + return Dictionary.TryGetValue(baseCameraToy, out CameraToy item) ? item : (CameraToy)CreateAdminToyWrapper(baseCameraToy); + } + + /// + /// Tries to get the camera toy wrapper from the . + /// + /// The of the camera toy. + /// The requested camera toy. + /// True if the camera toy exists, otherwise false. + public static bool TryGet(Scp079CameraToy? baseCameraToy, [NotNullWhen(true)] out CameraToy? cameraToy) + { + cameraToy = Get(baseCameraToy); + return cameraToy != null; + } /// /// An internal constructor to prevent external instantiation. @@ -27,17 +88,12 @@ public class CameraToy : AdminToy internal CameraToy(Scp079CameraToy baseCameraToy) : base(baseCameraToy) { - Dictionary.Add(baseCameraToy, this); Base = baseCameraToy; - } - /// - /// An internal method to remove itself from the cache when the base object is destroyed. - /// - internal override void OnRemove() - { - base.OnRemove(); - Dictionary.Remove(Base); + if (CanCache) + { + Dictionary.Add(baseCameraToy, this); + } } /// @@ -45,11 +101,10 @@ internal override void OnRemove() /// public new Scp079CameraToy Base { get; } - // Todo: reimplement when publicized - // /// - // /// The camera instance associated with this toy. - // /// - // public Camera Camera => Camera.Get(Base.Camera); + /// + /// The camera instance associated with this toy. + /// + public Camera Camera => Camera.Get(Base.Camera); /// /// Gets or sets the label of the camera displayed to SCP-079 on HUD. @@ -101,7 +156,7 @@ public Vector2 HorizontalConstraint /// Gets or set the min and max zoom level of the camera. /// /// - /// Values range from 0.0 to 1.0, with zero being the minimum zoom, and 1 being the maximum zoom. + /// Values range from 0.0 to 1.0, with zero being the minimum zoom, and 1 being the maximum zoom. /// X should be less than or equal to y. /// public Vector2 ZoomConstraints @@ -110,60 +165,12 @@ public Vector2 ZoomConstraints set => Base.NetworkZoomConstraint = value; } - /// - public static CameraToy Create(Transform? parent = null, bool networkSpawn = true) - => Create(Vector3.zero, parent, networkSpawn); - - /// - public static CameraToy Create(Vector3 position, Transform? parent = null, bool networkSpawn = true) - => Create(position, Quaternion.identity, parent, networkSpawn); - - /// - public static CameraToy Create(Vector3 position, Quaternion rotation, Transform? parent = null, bool networkSpawn = true) - => Create(position, rotation, Vector3.one, parent, networkSpawn); - /// - /// Creates a new camera toy. - /// - /// The initial local position. - /// The initial local rotation. - /// The initial local scale. - /// The parent transform. - /// Whether to spawn the toy on the client. - /// The created camera toy. - public static CameraToy Create(Vector3 position, Quaternion rotation, Vector3 scale, Transform? parent = null, bool networkSpawn = true) - { - CameraToy toy = Get(Create(position, rotation, scale, parent)); - - if (networkSpawn) - toy.Spawn(); - - return toy; - } - - /// - /// Gets the camera toy wrapper from the or creates a new one if it doesn't exist and the provided was not . - /// - /// The of the camera toy. - /// The requested camera toy or . - [return: NotNullIfNotNull(nameof(baseCameraToy))] - public static CameraToy? Get(Scp079CameraToy? baseCameraToy) - { - if (baseCameraToy == null) - return null; - - return Dictionary.TryGetValue(baseCameraToy, out CameraToy item) ? item : (CameraToy)CreateAdminToyWrapper(baseCameraToy); - } - - /// - /// Tries to get the camera toy wrapper from the . + /// An internal method to remove itself from the cache when the base object is destroyed. /// - /// The of the camera toy. - /// The requested camera toy. - /// True if the camera toy exists, otherwise false. - public static bool TryGet(Scp079CameraToy? baseCameraToy, [NotNullWhen(true)] out CameraToy? cameraToy) + internal override void OnRemove() { - cameraToy = Get(baseCameraToy); - return cameraToy != null; + base.OnRemove(); + Dictionary.Remove(Base); } } diff --git a/LabApi/Features/Wrappers/AdminToys/CapybaraToy.cs b/LabApi/Features/Wrappers/AdminToys/CapybaraToy.cs index 28630112..2f703443 100644 --- a/LabApi/Features/Wrappers/AdminToys/CapybaraToy.cs +++ b/LabApi/Features/Wrappers/AdminToys/CapybaraToy.cs @@ -13,45 +13,12 @@ public class CapybaraToy : AdminToy /// /// Contains all the capybara toys, accessible through their . /// - public new static Dictionary Dictionary { get; } = []; + public static new Dictionary Dictionary { get; } = []; /// /// A reference to all instances of . /// - public new static IReadOnlyCollection List => Dictionary.Values; - - /// - /// An internal constructor to prevent external instantiation. - /// - /// The base object. - internal CapybaraToy(BaseCapybaraToy baseCapybaraToy) : base(baseCapybaraToy) - { - Dictionary.Add(baseCapybaraToy, this); - Base = baseCapybaraToy; - } - - /// - /// An internal method to remove itself from the cache when the base object is destroyed. - /// - internal override void OnRemove() - { - base.OnRemove(); - Dictionary.Remove(Base); - } - - /// - /// The object. - /// - public new BaseCapybaraToy Base { get; } - - /// - /// Gets or sets whether the capybara has enabled colliders. - /// - public bool CollidersEnabled - { - get => Base.CollisionsEnabled; - set => Base.CollisionsEnabled = value; - } + public static new IReadOnlyCollection List => Dictionary.Values; /// public static CapybaraToy Create(Transform? parent = null, bool networkSpawn = true) @@ -79,7 +46,9 @@ public static CapybaraToy Create(Vector3 position, Quaternion rotation, Vector3 CapybaraToy toy = Get(Create(position, rotation, scale, parent)); if (networkSpawn) + { toy.Spawn(); + } return toy; } @@ -93,8 +62,48 @@ public static CapybaraToy Create(Vector3 position, Quaternion rotation, Vector3 public static CapybaraToy? Get(BaseCapybaraToy? baseCapybaraToy) { if (baseCapybaraToy == null) + { return null; + } return Dictionary.TryGetValue(baseCapybaraToy, out CapybaraToy toy) ? toy : (CapybaraToy)CreateAdminToyWrapper(baseCapybaraToy); } + + /// + /// An internal constructor to prevent external instantiation. + /// + /// The base object. + internal CapybaraToy(BaseCapybaraToy baseCapybaraToy) + : base(baseCapybaraToy) + { + Base = baseCapybaraToy; + + if (CanCache) + { + Dictionary.Add(baseCapybaraToy, this); + } + } + + /// + /// The object. + /// + public new BaseCapybaraToy Base { get; } + + /// + /// Gets or sets whether the capybara has enabled colliders. + /// + public bool CollidersEnabled + { + get => Base.CollisionsEnabled; + set => Base.CollisionsEnabled = value; + } + + /// + /// An internal method to remove itself from the cache when the base object is destroyed. + /// + internal override void OnRemove() + { + base.OnRemove(); + Dictionary.Remove(Base); + } } diff --git a/LabApi/Features/Wrappers/AdminToys/InteractableToy.cs b/LabApi/Features/Wrappers/AdminToys/InteractableToy.cs index 6a1d7e24..9727b8a4 100644 --- a/LabApi/Features/Wrappers/AdminToys/InteractableToy.cs +++ b/LabApi/Features/Wrappers/AdminToys/InteractableToy.cs @@ -14,37 +14,88 @@ public class InteractableToy : AdminToy /// /// Contains all the interactable toys, accessible through their . /// - public new static Dictionary Dictionary { get; } = []; + public static new Dictionary Dictionary { get; } = []; /// /// A reference to all instances of . /// - public new static IReadOnlyCollection List => Dictionary.Values; + public static new IReadOnlyCollection List => Dictionary.Values; + + /// + public static InteractableToy Create(Transform? parent = null, bool networkSpawn = true) + => Create(Vector3.zero, parent, networkSpawn); + + /// + public static InteractableToy Create(Vector3 position, Transform? parent = null, bool networkSpawn = true) + => Create(position, Quaternion.identity, parent, networkSpawn); + + /// + public static InteractableToy Create(Vector3 position, Quaternion rotation, Transform? parent = null, bool networkSpawn = true) + => Create(position, rotation, Vector3.one, parent, networkSpawn); /// - /// An internal constructor to prevent external instantiation. + /// Creates a new interactable toy. /// - /// The base object. - internal InteractableToy(InvisibleInteractableToy baseInteractableToy) - :base(baseInteractableToy) + /// The initial local position. + /// The initial local rotation. + /// The initial local scale. + /// The parent transform. + /// Whether to spawn the toy on the client. + /// The created interactable toy. + public static InteractableToy Create(Vector3 position, Quaternion rotation, Vector3 scale, Transform? parent = null, bool networkSpawn = true) { - Dictionary.Add(baseInteractableToy, this); - Base = baseInteractableToy; + InteractableToy toy = Get(Create(position, rotation, scale, parent)); + + if (networkSpawn) + { + toy.Spawn(); + } + + return toy; } /// - /// An internal method to remove itself from the cache when the base object is destroyed. + /// Gets the interactable toy wrapper from the or creates a new one if it doesn't exist and the provided was not . /// - internal override void OnRemove() + /// The of the interactable toy. + /// The requested interactable toy or . + [return: NotNullIfNotNull(nameof(baseInteractableToy))] + public static InteractableToy? Get(InvisibleInteractableToy? baseInteractableToy) { - base.OnRemove(); - Dictionary.Remove(Base); + if (baseInteractableToy == null) + { + return null; + } + + return Dictionary.TryGetValue(baseInteractableToy, out InteractableToy item) ? item : (InteractableToy)CreateAdminToyWrapper(baseInteractableToy); } /// - /// The object. + /// Tries to get the interactable toy wrapper from the . /// - public new InvisibleInteractableToy Base { get; } + /// The of the interactable toy. + /// The requested interactable toy. + /// True if the interactable toy exists, otherwise false. + public static bool TryGet(InvisibleInteractableToy? baseInteractableToy, [NotNullWhen(true)] out InteractableToy? interactableToy) + { + interactableToy = Get(baseInteractableToy); + return interactableToy != null; + } + + /// + /// An internal constructor to prevent external instantiation. + /// + /// The base object. + internal InteractableToy(InvisibleInteractableToy baseInteractableToy) + : base(baseInteractableToy) + { + Base = baseInteractableToy; + + if (CanCache) + { + Dictionary.Add(baseInteractableToy, this); + } + } /// /// Event called when a interacts with the toy. @@ -54,16 +105,21 @@ public event Action OnInteracted add { if (InternalOnInteracted == null) + { Base.OnInteracted += InvokeOnInteracted; + } InternalOnInteracted += value; } + remove { InternalOnInteracted -= value; if (InternalOnInteracted == null) + { Base.OnInteracted -= InvokeOnInteracted; + } } } @@ -75,16 +131,21 @@ public event Action OnSearching add { if (InternalOnSearching == null) + { Base.OnSearching += InvokeOnSearching; + } InternalOnSearching += value; } + remove { InternalOnSearching -= value; if (InternalOnSearching == null) + { Base.OnSearching -= InvokeOnSearching; + } } } @@ -96,16 +157,21 @@ public event Action OnSearched add { if (InternalOnSearched == null) + { Base.OnSearched += InvokeOnSearched; + } InternalOnSearched += value; } + remove { InternalOnSearched -= value; if (InternalOnSearched == null) + { Base.OnSearched -= InvokeOnSearched; + } } } @@ -117,19 +183,37 @@ public event Action OnSearchAborted add { if (InternalOnSearchAborted == null) + { Base.OnSearched += InvokeOnSearchAborted; + } InternalOnSearchAborted += value; } + remove { InternalOnSearchAborted -= value; if (InternalOnSearchAborted == null) + { Base.OnSearched -= InvokeOnSearchAborted; + } } } + private event Action? InternalOnInteracted; + + private event Action? InternalOnSearching; + + private event Action? InternalOnSearched; + + private event Action? InternalOnSearchAborted; + + /// + /// The object. + /// + public new InvisibleInteractableToy Base { get; } + /// /// Gets or sets the shape of the collider used for interactions. /// @@ -171,13 +255,14 @@ public bool IsLocked /// public bool CanSearch => Base.CanSearch; - private event Action? InternalOnInteracted; - - private event Action? InternalOnSearching; - - private event Action? InternalOnSearched; - - private event Action? InternalOnSearchAborted; + /// + /// An internal method to remove itself from the cache when the base object is destroyed. + /// + internal override void OnRemove() + { + base.OnRemove(); + Dictionary.Remove(Base); + } private void InvokeOnInteracted(ReferenceHub hub) => InternalOnInteracted?.Invoke(Player.Get(hub)); @@ -186,61 +271,4 @@ public bool IsLocked private void InvokeOnSearched(ReferenceHub hub) => InternalOnSearched?.Invoke(Player.Get(hub)); private void InvokeOnSearchAborted(ReferenceHub hub) => InternalOnSearchAborted?.Invoke(Player.Get(hub)); - - /// - public static InteractableToy Create(Transform? parent = null, bool networkSpawn = true) - => Create(Vector3.zero, parent, networkSpawn); - - /// - public static InteractableToy Create(Vector3 position, Transform? parent = null, bool networkSpawn = true) - => Create(position, Quaternion.identity, parent, networkSpawn); - - /// - public static InteractableToy Create(Vector3 position, Quaternion rotation, Transform? parent = null, bool networkSpawn = true) - => Create(position, rotation, Vector3.one, parent, networkSpawn); - - /// - /// Creates a new interactable toy. - /// - /// The initial local position. - /// The initial local rotation. - /// The initial local scale. - /// The parent transform. - /// Whether to spawn the toy on the client. - /// The created interactable toy. - public static InteractableToy Create(Vector3 position, Quaternion rotation, Vector3 scale, Transform? parent = null, bool networkSpawn = true) - { - InteractableToy toy = Get(Create(position, rotation, scale, parent)); - - if (networkSpawn) - toy.Spawn(); - - return toy; - } - - /// - /// Gets the interactable toy wrapper from the or creates a new one if it doesn't exist and the provided was not . - /// - /// The of the interactable toy. - /// The requested interactable toy or . - [return: NotNullIfNotNull(nameof(baseInteractableToy))] - public static InteractableToy? Get(InvisibleInteractableToy? baseInteractableToy) - { - if (baseInteractableToy == null) - return null; - - return Dictionary.TryGetValue(baseInteractableToy, out InteractableToy item) ? item : (InteractableToy)CreateAdminToyWrapper(baseInteractableToy); - } - - /// - /// Tries to get the interactable toy wrapper from the . - /// - /// The of the interactable toy. - /// The requested interactable toy. - /// True if the interactable toy exists, otherwise false. - public static bool TryGet(InvisibleInteractableToy? baseInteractableToy, [NotNullWhen(true)] out InteractableToy? interactableToy) - { - interactableToy = Get(baseInteractableToy); - return interactableToy != null; - } } diff --git a/LabApi/Features/Wrappers/AdminToys/LightSourceToy.cs b/LabApi/Features/Wrappers/AdminToys/LightSourceToy.cs index b428c2fa..c442f09a 100644 --- a/LabApi/Features/Wrappers/AdminToys/LightSourceToy.cs +++ b/LabApi/Features/Wrappers/AdminToys/LightSourceToy.cs @@ -13,12 +13,73 @@ public class LightSourceToy : AdminToy /// /// Contains all the light source toys, accessible through their . /// - public new static Dictionary Dictionary { get; } = []; + public static new Dictionary Dictionary { get; } = []; /// /// A reference to all instances of . /// - public new static IReadOnlyCollection List => Dictionary.Values; + public static new IReadOnlyCollection List => Dictionary.Values; + + /// + public static LightSourceToy Create(Transform? parent = null, bool networkSpawn = true) + => Create(Vector3.zero, parent, networkSpawn); + + /// + public static LightSourceToy Create(Vector3 position, Transform? parent = null, bool networkSpawn = true) + => Create(position, Quaternion.identity, parent, networkSpawn); + + /// + public static LightSourceToy Create(Vector3 position, Quaternion rotation, Transform? parent = null, bool networkSpawn = true) + => Create(position, rotation, Vector3.one, parent, networkSpawn); + + /// + /// Creates a new light source toy. + /// + /// The initial local position. + /// The initial local rotation. + /// The initial local scale. + /// The parent transform. + /// Whether to spawn the toy on the client. + /// The created light source toy. + public static LightSourceToy Create(Vector3 position, Quaternion rotation, Vector3 scale, Transform? parent = null, bool networkSpawn = true) + { + LightSourceToy toy = Get(Create(position, rotation, scale, parent)); + + if (networkSpawn) + { + toy.Spawn(); + } + + return toy; + } + + /// + /// Gets the light source toy wrapper from the or creates a new one if it doesn't exist and the provided was not . + /// + /// The of the light source toy. + /// The requested light source toy or . + [return: NotNullIfNotNull(nameof(baseLightSourceToy))] + public static LightSourceToy? Get(BaseLightSourceToy? baseLightSourceToy) + { + if (baseLightSourceToy == null) + { + return null; + } + + return Dictionary.TryGetValue(baseLightSourceToy, out LightSourceToy item) ? item : (LightSourceToy)CreateAdminToyWrapper(baseLightSourceToy); + } + + /// + /// Tries to get the light source toy wrapper from the . + /// + /// The of the light source toy. + /// The requested light source toy. + /// if the light toy exists, otherwise . + public static bool TryGet(BaseLightSourceToy? baseLightSourceToy, [NotNullWhen(true)] out LightSourceToy? lightSourceToy) + { + lightSourceToy = Get(baseLightSourceToy); + return lightSourceToy != null; + } /// /// An internal constructor to prevent external instantiation. @@ -27,17 +88,12 @@ public class LightSourceToy : AdminToy internal LightSourceToy(BaseLightSourceToy baseLightSourceToy) : base(baseLightSourceToy) { - Dictionary.Add(baseLightSourceToy, this); Base = baseLightSourceToy; - } - /// - /// An internal method to remove itself from the cache when the base object is destroyed. - /// - internal override void OnRemove() - { - base.OnRemove(); - Dictionary.Remove(Base); + if (CanCache) + { + Dictionary.Add(baseLightSourceToy, this); + } } /// @@ -102,7 +158,9 @@ public LightType Type /// /// Gets or sets the lights . /// +#pragma warning disable CS0618 // Type or member is obsolete public LightShape Shape +#pragma warning restore CS0618 // Type or member is obsolete { get => Base.LightShape; set => Base.NetworkLightShape = value; @@ -132,60 +190,12 @@ public override string ToString() return $"[LightSourceToy: Type={Type}, Shape={Shape}, Intensity={Intensity}, Range={Range}, Color={Color}, ShadowType={ShadowType}, ShadowStrength={ShadowStrength}]"; } - /// - public static LightSourceToy Create(Transform? parent = null, bool networkSpawn = true) - => Create(Vector3.zero, parent, networkSpawn); - - /// - public static LightSourceToy Create(Vector3 position, Transform? parent = null, bool networkSpawn = true) - => Create(position, Quaternion.identity, parent, networkSpawn); - - /// - public static LightSourceToy Create(Vector3 position, Quaternion rotation, Transform? parent = null, bool networkSpawn = true) - => Create(position, rotation, Vector3.one, parent, networkSpawn); - - /// - /// Creates a new light source toy. - /// - /// The initial local position. - /// The initial local rotation. - /// The initial local scale. - /// The parent transform. - /// Whether to spawn the toy on the client. - /// The created light source toy. - public static LightSourceToy Create(Vector3 position, Quaternion rotation, Vector3 scale, Transform? parent = null, bool networkSpawn = true) - { - LightSourceToy toy = Get(Create(position, rotation, scale, parent)); - - if (networkSpawn) - toy.Spawn(); - - return toy; - } - - /// - /// Gets the light source toy wrapper from the or creates a new one if it doesn't exist and the provided was not . - /// - /// The of the light source toy. - /// The requested light source toy or . - [return: NotNullIfNotNull(nameof(baseLightSourceToy))] - public static LightSourceToy? Get(BaseLightSourceToy? baseLightSourceToy) - { - if (baseLightSourceToy == null) - return null; - - return Dictionary.TryGetValue(baseLightSourceToy, out LightSourceToy item) ? item : (LightSourceToy)CreateAdminToyWrapper(baseLightSourceToy); - } - /// - /// Tries to get the light source toy wrapper from the . + /// An internal method to remove itself from the cache when the base object is destroyed. /// - /// The of the light source toy. - /// The requested light source toy. - /// if the light toy exists, otherwise . - public static bool TryGet(BaseLightSourceToy? baseLightSourceToy, [NotNullWhen(true)] out LightSourceToy? lightSourceToy) + internal override void OnRemove() { - lightSourceToy = Get(baseLightSourceToy); - return lightSourceToy != null; + base.OnRemove(); + Dictionary.Remove(Base); } } diff --git a/LabApi/Features/Wrappers/AdminToys/PrimitiveObjectToy.cs b/LabApi/Features/Wrappers/AdminToys/PrimitiveObjectToy.cs index 62196bf9..ba5c4fad 100644 --- a/LabApi/Features/Wrappers/AdminToys/PrimitiveObjectToy.cs +++ b/LabApi/Features/Wrappers/AdminToys/PrimitiveObjectToy.cs @@ -14,73 +14,12 @@ public class PrimitiveObjectToy : AdminToy /// /// Contains all the primitive object toys, accessible through their . /// - public new static Dictionary Dictionary { get; } = []; + public static new Dictionary Dictionary { get; } = []; /// /// A reference to all instances of . /// - public new static IReadOnlyCollection List => Dictionary.Values; - - /// - /// An internal constructor to prevent external instantiation. - /// - /// The base object. - internal PrimitiveObjectToy(BasePrimitiveObjectToy basePrimitiveObjectToy) - : base(basePrimitiveObjectToy) - { - Dictionary.Add(basePrimitiveObjectToy, this); - Base = basePrimitiveObjectToy; - } - - /// - /// An internal method to remove itself from the cache when the base object is destroyed. - /// - internal override void OnRemove() - { - base.OnRemove(); - Dictionary.Remove(Base); - } - - /// - /// The object. - /// - public new BasePrimitiveObjectToy Base { get; } - - /// - /// Gets or sets the . - /// - public PrimitiveType Type - { - get => Base.PrimitiveType; - set => Base.NetworkPrimitiveType = value; - } - - /// - /// Gets or sets the material . - /// - public Color Color - { - get => Base.MaterialColor; - set => Base.NetworkMaterialColor = value; - } - - /// - /// Gets or sets the . - /// - /// - /// Setting flags to is similar to having an empty object which is useful as a root object other toys parent to. - /// - public PrimitiveFlags Flags - { - get => Base.PrimitiveFlags; - set => Base.NetworkPrimitiveFlags = value; - } - - /// - public override string ToString() - { - return $"[PrimitiveObjectToy: Type={Type}, Color={Color}, Flags={Flags}]"; - } + public static new IReadOnlyCollection List => Dictionary.Values; /// public static PrimitiveObjectToy Create(Transform? parent = null, bool networkSpawn = true) @@ -108,7 +47,9 @@ public static PrimitiveObjectToy Create(Vector3 position, Quaternion rotation, V PrimitiveObjectToy toy = Get(Create(position, rotation, scale, parent)); if (networkSpawn) + { toy.Spawn(); + } return toy; } @@ -122,7 +63,9 @@ public static PrimitiveObjectToy Create(Vector3 position, Quaternion rotation, V public static PrimitiveObjectToy? Get(BasePrimitiveObjectToy? primitiveObjectToy) { if (primitiveObjectToy == null) + { return null; + } return Dictionary.TryGetValue(primitiveObjectToy, out PrimitiveObjectToy item) ? item : (PrimitiveObjectToy)CreateAdminToyWrapper(primitiveObjectToy); } @@ -138,4 +81,69 @@ public static bool TryGet(BasePrimitiveObjectToy? basePrimitiveObjectToy, [NotNu primitiveObjectToy = Get(basePrimitiveObjectToy); return primitiveObjectToy != null; } + + /// + /// An internal constructor to prevent external instantiation. + /// + /// The base object. + internal PrimitiveObjectToy(BasePrimitiveObjectToy basePrimitiveObjectToy) + : base(basePrimitiveObjectToy) + { + Base = basePrimitiveObjectToy; + + if (CanCache) + { + Dictionary.Add(basePrimitiveObjectToy, this); + } + } + + /// + /// The object. + /// + public new BasePrimitiveObjectToy Base { get; } + + /// + /// Gets or sets the . + /// + public PrimitiveType Type + { + get => Base.PrimitiveType; + set => Base.NetworkPrimitiveType = value; + } + + /// + /// Gets or sets the material . + /// + public Color Color + { + get => Base.MaterialColor; + set => Base.NetworkMaterialColor = value; + } + + /// + /// Gets or sets the . + /// + /// + /// Setting flags to is similar to having an empty object which is useful as a root object other toys parent to. + /// + public PrimitiveFlags Flags + { + get => Base.PrimitiveFlags; + set => Base.NetworkPrimitiveFlags = value; + } + + /// + public override string ToString() + { + return $"[PrimitiveObjectToy: Type={Type}, Color={Color}, Flags={Flags}]"; + } + + /// + /// An internal method to remove itself from the cache when the base object is destroyed. + /// + internal override void OnRemove() + { + base.OnRemove(); + Dictionary.Remove(Base); + } } diff --git a/LabApi/Features/Wrappers/AdminToys/ShootingTargetToy.cs b/LabApi/Features/Wrappers/AdminToys/ShootingTargetToy.cs index 4699f031..6f5281cc 100644 --- a/LabApi/Features/Wrappers/AdminToys/ShootingTargetToy.cs +++ b/LabApi/Features/Wrappers/AdminToys/ShootingTargetToy.cs @@ -13,65 +13,25 @@ public class ShootingTargetToy : AdminToy /// /// Contains all the shooting target toys, accessible through their . /// - public new static Dictionary Dictionary { get; } = []; + public static new Dictionary Dictionary { get; } = []; /// /// A reference to all instances of . /// - public new static IReadOnlyCollection List => Dictionary.Values; - - /// - /// An internal constructor to prevent external instantiation. - /// - /// The base object. - internal ShootingTargetToy(ShootingTarget shootingTarget) - : base(shootingTarget) - { - Dictionary.Add(shootingTarget, this); - Base = shootingTarget; - } - - /// - /// An internal method to remove itself from the cache when the base object is destroyed. - /// - internal override void OnRemove() - { - base.OnRemove(); - Dictionary.Remove(Base); - } - - /// - /// The object. - /// - public new ShootingTarget Base { get; } - - /// - /// Gets or sets whether other players can see your interactions. - /// - public bool IsGlobal - { - get => Base.Network_syncMode; - set => Base.Network_syncMode = value; - } - - /// - public override string ToString() - { - return $"[ShootingTargetToy: IsGlobal={IsGlobal}]"; - } + public static new IReadOnlyCollection List => Dictionary.Values; /// - // BUG: you can only spawn one of the shooting target types and you dont get to choose which. + // BUG: you can only spawn one of the shooting target types and you don't get to choose which. public static ShootingTargetToy Create(Transform? parent = null, bool networkSpawn = true) => Create(Vector3.zero, parent, networkSpawn); /// - // BUG: you can only spawn one of the shooting target types and you dont get to choose which. + // BUG: you can only spawn one of the shooting target types and you don't get to choose which. public static ShootingTargetToy Create(Vector3 position, Transform? parent = null, bool networkSpawn = true) => Create(position, Quaternion.identity, parent, networkSpawn); /// - // BUG: you can only spawn one of the shooting target types and you dont get to choose which. + // BUG: you can only spawn one of the shooting target types and you don't get to choose which. public static ShootingTargetToy Create(Vector3 position, Quaternion rotation, Transform? parent = null, bool networkSpawn = true) => Create(position, rotation, Vector3.one, parent, networkSpawn); @@ -84,13 +44,15 @@ public static ShootingTargetToy Create(Vector3 position, Quaternion rotation, Tr /// The parent transform. /// Whether to spawn the toy on the client. /// The created shooting target toy. - // BUG: you can only spawn one of the shooting target types and you dont get to choose which. + // BUG: you can only spawn one of the shooting target types and you don't get to choose which. public static ShootingTargetToy Create(Vector3 position, Quaternion rotation, Vector3 scale, Transform? parent = null, bool networkSpawn = true) { ShootingTargetToy toy = Get(Create(position, rotation, scale, parent)); if (networkSpawn) + { toy.Spawn(); + } return toy; } @@ -104,7 +66,9 @@ public static ShootingTargetToy Create(Vector3 position, Quaternion rotation, Ve public static ShootingTargetToy? Get(ShootingTarget? shootingTarget) { if (shootingTarget == null) + { return null; + } return Dictionary.TryGetValue(shootingTarget, out ShootingTargetToy toy) ? toy : (ShootingTargetToy)CreateAdminToyWrapper(shootingTarget); } @@ -120,4 +84,48 @@ public static bool TryGet(ShootingTarget? shootingTarget, [NotNullWhen(true)] ou shootingTargetToy = Get(shootingTarget); return shootingTargetToy != null; } + + /// + /// An internal constructor to prevent external instantiation. + /// + /// The base object. + internal ShootingTargetToy(ShootingTarget shootingTarget) + : base(shootingTarget) + { + Base = shootingTarget; + + if (CanCache) + { + Dictionary.Add(shootingTarget, this); + } + } + + /// + /// The object. + /// + public new ShootingTarget Base { get; } + + /// + /// Gets or sets whether other players can see your interactions. + /// + public bool IsGlobal + { + get => Base.Network_syncMode; + set => Base.Network_syncMode = value; + } + + /// + public override string ToString() + { + return $"[ShootingTargetToy: IsGlobal={IsGlobal}]"; + } + + /// + /// An internal method to remove itself from the cache when the base object is destroyed. + /// + internal override void OnRemove() + { + base.OnRemove(); + Dictionary.Remove(Base); + } } diff --git a/LabApi/Features/Wrappers/AdminToys/SpawnableCullingParent.cs b/LabApi/Features/Wrappers/AdminToys/SpawnableCullingParent.cs new file mode 100644 index 00000000..d8b33354 --- /dev/null +++ b/LabApi/Features/Wrappers/AdminToys/SpawnableCullingParent.cs @@ -0,0 +1,207 @@ +using AdminToys; +using Generators; +using Mirror; +using System; +using System.Collections.Generic; +using System.Diagnostics.CodeAnalysis; +using UnityEngine; +using static LabApi.Features.Wrappers.AdminToy; +using BaseCullingParent = AdminToys.SpawnableCullingParent; +using Logger = LabApi.Features.Console.Logger; + +namespace LabApi.Features.Wrappers; + +/// +/// Wrapper for .
+/// Cullable item that deactivates itself when not being looked at. +/// Can contain children admin toys to cull them. +///
+/// +/// This class is not subclass of . +/// +public class SpawnableCullingParent +{ + /// + /// Contains all the cached spawnable culling parents, accessible through their . + /// + public static Dictionary Dictionary { get; } = []; + + /// + /// A reference to all instances of . + /// + public static IReadOnlyCollection List => Dictionary.Values; + + /// + /// Instantiates a new culling parent object. + /// + /// The initial position. + /// The bounds size. + /// Whether should the game object spawn over network. + /// The instantiated culling parent. + public static SpawnableCullingParent Create(Vector3 position, Vector3 size, bool networkSpawn = true) + { + if (PrefabCache.Prefab == null) + { + BaseCullingParent? found = null; + foreach (GameObject prefab in NetworkClient.prefabs.Values) + { + if (prefab.TryGetComponent(out found)) + { + break; + } + } + + if (found == null) + { + throw new InvalidOperationException($"No prefab in NetworkClient.prefabs has component type {typeof(BaseCullingParent)}"); + } + + PrefabCache.Prefab = found; + } + + BaseCullingParent instance = UnityEngine.Object.Instantiate(PrefabCache.Prefab, position, Quaternion.identity); + instance.NetworkBoundsPosition = position; + instance.NetworkBoundsSize = size; + + if (networkSpawn) + { + NetworkServer.Spawn(instance.gameObject); + } + + return Get(instance); + } + + /// + /// Gets the cullable parent wrapper from the or creates a new one if it doesn't exist and the provided was not . + /// + /// The of the cullable parent. + /// The requested culling parent or . + [return: NotNullIfNotNull(nameof(cullingBase))] + public static SpawnableCullingParent? Get(BaseCullingParent? cullingBase) + { + if (cullingBase == null) + { + return null; + } + + return Dictionary.TryGetValue(cullingBase, out SpawnableCullingParent item) ? item : new SpawnableCullingParent(cullingBase); + } + + /// + /// Tries to get the culling parent wrapper from the . + /// + /// The of the cullable parent. + /// The requested culling parent. + /// if the culling parent exists, otherwise . + public static bool TryGet(BaseCullingParent? adminToyBase, [NotNullWhen(true)] out SpawnableCullingParent? adminToy) + { + adminToy = Get(adminToyBase); + return adminToy != null; + } + + /// + /// Initializes the class. + /// + [InitializeWrapper] + internal static void Initialize() + { + BaseCullingParent.OnAdded += AddCullableParent; + BaseCullingParent.OnRemoved += RemoveCullableParent; + } + + /// + /// A private method to handle the creation of new cullable parents on the server. + /// + /// The created instance. + private static void AddCullableParent(BaseCullingParent cullableParent) + { + try + { + if (!Dictionary.ContainsKey(cullableParent)) + { + _ = new SpawnableCullingParent(cullableParent); + } + } + catch (Exception e) + { + Logger.InternalError($"Failed to handle cullable parent creation with error: {e}"); + } + } + + /// + /// A private method to handle the removal of cullable parents from the server. + /// + /// The to be destroyed instance. + private static void RemoveCullableParent(BaseCullingParent cullableParent) + { + try + { + Dictionary.Remove(cullableParent); + } + catch (Exception e) + { + Logger.InternalError($"Failed to handle cullable parent destruction with error: {e}"); + } + } + + /// + /// A protected constructor to prevent external instantiation. + /// + /// The base object. + protected SpawnableCullingParent(BaseCullingParent cullingBase) + { + Dictionary.Add(cullingBase, this); + Base = cullingBase; + } + + /// + /// The base object. + /// + public BaseCullingParent Base { get; } + + /// + /// The . + /// + public GameObject GameObject => Base.gameObject; + + /// + /// The culling parent's . + /// + public Transform Transform => Base.transform; + + /// + /// Whether the was destroyed. + /// + /// + /// A destroyed object may not be used. + /// + public bool IsDestroyed => Base == null; + + /// + /// Gets or sets the position of the culling parent. + /// + public Vector3 Position + { + get => Base.NetworkBoundsPosition; + set => Base.NetworkBoundsPosition = value; + } + + /// + /// Gets or sets the culling bound size of the culling parent. + /// + public Vector3 Size + { + get => Base.NetworkBoundsSize; + set => Base.NetworkBoundsSize = value; + } + + /// + /// Spawns the culling parent on client. + /// + public void Spawn() => NetworkServer.Spawn(GameObject); + + /// + /// Destroys the culling parent on server and client. + /// + public void Destroy() => NetworkServer.Destroy(GameObject); +} \ No newline at end of file diff --git a/LabApi/Features/Wrappers/AdminToys/SpeakerToy.cs b/LabApi/Features/Wrappers/AdminToys/SpeakerToy.cs index 78c280d5..9abdb733 100644 --- a/LabApi/Features/Wrappers/AdminToys/SpeakerToy.cs +++ b/LabApi/Features/Wrappers/AdminToys/SpeakerToy.cs @@ -10,21 +10,135 @@ namespace LabApi.Features.Wrappers; /// -/// Wrapper for the class +/// Wrapper for the class. /// public class SpeakerToy : AdminToy { + private static readonly Dictionary TransmitterByControllerId = []; + /// /// Contains all the speaker toys, accessible through their . /// - public new static Dictionary Dictionary { get; } = []; + public static new Dictionary Dictionary { get; } = []; /// /// A reference to all instances of . /// - public new static IReadOnlyCollection List => Dictionary.Values; + public static new IReadOnlyCollection List => Dictionary.Values; - private static readonly Dictionary TransmitterByControllerId = []; + /// + /// Plays the PCM samples on the current controller. + /// + /// + /// Samples are played at a sample rate of , mono channel (non interleaved data) with ranges from -1.0f to 1.0f. + /// + /// The Id of the controller to play audio on. + /// The PCM samples. + /// Whether to queue the audio if audio is already playing, otherwise overrides the current audio. + /// + /// Whether to loop this clip. + /// Loop ends if another clip is played either immediately if not queued or at the end of the loop if next clip was queued. + /// + public static void Play(byte controllerId, float[] samples, bool queue = true, bool loop = false) + => GetTransmitter(controllerId).Play(samples, queue, loop); + + /// + /// The Id of the controller to play audio on. + public static void Pause(byte controllerId) => GetTransmitter(controllerId).Pause(); + + /// + /// The Id of the controller to play audio on. + public static void Resume(byte controllerId) => GetTransmitter(controllerId).Resume(); + + /// + /// Skips the current or queued clips. + /// Includes the current clip. + /// + /// The Id of the controller to play audio on. + /// The number of queued audios clips to skip. + public static void Skip(byte controllerId, int count) => GetTransmitter(controllerId).Skip(count); + + /// + /// The Id of the controller to play audio on. + public static void Stop(byte controllerId) => GetTransmitter(controllerId).Stop(); + + /// + public static SpeakerToy Create(Transform? parent = null, bool networkSpawn = true) + => Create(Vector3.zero, parent, networkSpawn); + + /// + public static SpeakerToy Create(Vector3 position, Transform? parent = null, bool networkSpawn = true) + => Create(position, Quaternion.identity, parent, networkSpawn); + + /// + public static SpeakerToy Create(Vector3 position, Quaternion rotation, Transform? parent = null, bool networkSpawn = true) + => Create(position, rotation, Vector3.one, parent, networkSpawn); + + /// + /// Creates a new speaker toy. + /// + /// The initial local position. + /// The initial local rotation. + /// The initial local scale. + /// The parent transform. + /// Whether to spawn the toy on the client. + /// The created speaker toy. + public static SpeakerToy Create(Vector3 position, Quaternion rotation, Vector3 scale, Transform? parent = null, bool networkSpawn = true) + { + SpeakerToy toy = Get(Create(position, rotation, scale, parent)); + + if (networkSpawn) + { + toy.Spawn(); + } + + return toy; + } + + /// + /// Gets the speaker toy wrapper from the or creates a new one if it doesn't exist and the provided was not . + /// + /// The of the speaker toy. + /// The requested speaker toy or . + [return: NotNullIfNotNull(nameof(baseSpeakerToy))] + public static SpeakerToy? Get(BaseSpeakerToy? baseSpeakerToy) + { + if (baseSpeakerToy == null) + { + return null; + } + + return Dictionary.TryGetValue(baseSpeakerToy, out SpeakerToy toy) ? toy : (SpeakerToy)CreateAdminToyWrapper(baseSpeakerToy); + } + + /// + /// Tries to get the speaker toy wrapper from the . + /// + /// The of the speaker toy. + /// The requested speaker toy. + /// if the speaker exists, otherwise . + public static bool TryGet(BaseSpeakerToy? baseSpeakerToy, [NotNullWhen(true)] out SpeakerToy? speakerToy) + { + speakerToy = Get(baseSpeakerToy); + return speakerToy != null; + } + + /// + /// Gets the for the . + /// If one does not exists, a new one is created for the id. + /// + /// The for the transmitter. + /// Cached transmitter. + public static AudioTransmitter GetTransmitter(byte controllerId) + { + if (!TransmitterByControllerId.TryGetValue(controllerId, out AudioTransmitter transmitter)) + { + transmitter = new(controllerId); + TransmitterByControllerId.Add(controllerId, transmitter); + } + + return transmitter; + } /// /// An internal constructor to prevent external instantiation. @@ -33,17 +147,12 @@ public class SpeakerToy : AdminToy internal SpeakerToy(BaseSpeakerToy baseSpeakerToy) : base(baseSpeakerToy) { - Dictionary.Add(baseSpeakerToy, this); Base = baseSpeakerToy; - } - /// - /// An internal method to remove itself from the cache when the base object is destroyed. - /// - internal override void OnRemove() - { - base.OnRemove(); - Dictionary.Remove(Base); + if (CanCache) + { + Dictionary.Add(baseSpeakerToy, this); + } } /// @@ -178,7 +287,7 @@ public Func? ValidPlayers } /// - /// Gets the audio transmitter for this speakers . + /// Gets the audio transmitter for this speakers . /// /// /// Speakers can share instances if they have the same . @@ -208,112 +317,11 @@ public override string ToString() } /// - /// Plays the PCM samples on the current controller. - /// - /// - /// Samples are played at a sample rate of , mono channel (non interleaved data) with ranges from -1.0f to 1.0f. - /// - /// The Id of the controller to play audio on. - /// The PCM samples. - /// Whether to queue the audio if audio is already playing, otherwise overrides the current audio. - /// - /// Whether to loop this clip. - /// Loop ends if another clip is played either immediately if not queued or at the end of the loop if next clip was queued. - /// - public static void Play(byte controllerId, float[] samples, bool queue = true, bool loop = false) - => GetTransmitter(controllerId).Play(samples, queue, loop); - - /// - /// The Id of the controller to play audio on. - public static void Pause(byte controllerId) => GetTransmitter(controllerId).Pause(); - - /// - /// The Id of the controller to play audio on. - public static void Resume(byte controllerId) => GetTransmitter(controllerId).Resume(); - - /// - /// Skips the current or queued clips. - /// Includes the current clip. - /// - /// The Id of the controller to play audio on. - /// The number of queued audios clips to skip. - public static void Skip(byte controllerId, int count) => GetTransmitter(controllerId).Skip(count); - - /// - /// The Id of the controller to play audio on. - public static void Stop(byte controllerId) => GetTransmitter(controllerId).Stop(); - - /// - public static SpeakerToy Create(Transform? parent = null, bool networkSpawn = true) - => Create(Vector3.zero, parent, networkSpawn); - - /// - public static SpeakerToy Create(Vector3 position, Transform? parent = null, bool networkSpawn = true) - => Create(position, Quaternion.identity, parent, networkSpawn); - - /// - public static SpeakerToy Create(Vector3 position, Quaternion rotation, Transform? parent = null, bool networkSpawn = true) - => Create(position, rotation, Vector3.one, parent, networkSpawn); - - /// - /// Creates a new speaker toy. - /// - /// The initial local position. - /// The initial local rotation. - /// The initial local scale. - /// The parent transform. - /// Whether to spawn the toy on the client. - /// The created speaker toy. - public static SpeakerToy Create(Vector3 position, Quaternion rotation, Vector3 scale, Transform? parent = null, bool networkSpawn = true) - { - SpeakerToy toy = Get(Create(position, rotation, scale, parent)); - - if (networkSpawn) - toy.Spawn(); - - return toy; - } - - /// - /// Gets the speaker toy wrapper from the or creates a new one if it doesn't exist and the provided was not . - /// - /// The of the speaker toy. - /// The requested speaker toy or . - [return: NotNullIfNotNull(nameof(baseSpeakerToy))] - public static SpeakerToy? Get(BaseSpeakerToy? baseSpeakerToy) - { - if (baseSpeakerToy == null) - return null; - - return Dictionary.TryGetValue(baseSpeakerToy, out SpeakerToy toy) ? toy : (SpeakerToy)CreateAdminToyWrapper(baseSpeakerToy); - } - - /// - /// Tries to get the speaker toy wrapper from the . - /// - /// The of the speaker toy. - /// The requested speaker toy. - /// if the speaker exists, otherwise . - public static bool TryGet(BaseSpeakerToy? baseSpeakerToy, [NotNullWhen(true)] out SpeakerToy? speakerToy) - { - speakerToy = Get(baseSpeakerToy); - return speakerToy != null; - } - - /// - /// Gets the for the . - /// If one does not exists, a new one is created for the id. + /// An internal method to remove itself from the cache when the base object is destroyed. /// - /// The for the transmitter. - /// - public static AudioTransmitter GetTransmitter(byte controllerId) + internal override void OnRemove() { - if (!TransmitterByControllerId.TryGetValue(controllerId, out AudioTransmitter transmitter)) - { - transmitter = new(controllerId); - TransmitterByControllerId.Add(controllerId, transmitter); - } - - return transmitter; + base.OnRemove(); + Dictionary.Remove(Base); } } diff --git a/LabApi/Features/Wrappers/AdminToys/TextToy.cs b/LabApi/Features/Wrappers/AdminToys/TextToy.cs index f2469f5e..0e628b4d 100644 --- a/LabApi/Features/Wrappers/AdminToys/TextToy.cs +++ b/LabApi/Features/Wrappers/AdminToys/TextToy.cs @@ -8,67 +8,19 @@ namespace LabApi.Features.Wrappers; /// /// The wrapper for the class.
-/// Toy with changable text and formatting arguments. +/// Toy with changeable text and formatting arguments. ///
public class TextToy : AdminToy { /// /// Contains all the text toys, accessible through their . /// - public new static Dictionary Dictionary { get; } = []; + public static new Dictionary Dictionary { get; } = []; /// /// A reference to all instances of . /// - public new static IReadOnlyCollection List => Dictionary.Values; - - /// - /// An internal constructor to prevent external instantiation. - /// - /// The base object. - internal TextToy(BaseTextToy baseToy) : base(baseToy) - { - Base = baseToy; - } - - /// - /// An internal method to remove itself from the cache when the base object is destroyed. - /// - internal override void OnRemove() - { - base.OnRemove(); - Dictionary.Remove(Base); - } - - /// - /// The object. - /// - public new BaseTextToy Base { get; } - - /// - /// Gets or sets the base text format used when formatting the final text string.
- /// Text can be formatted and arguments are replaced with . - ///
- public string TextFormat - { - get => Base.TextFormat; - set => Base.TextFormat = value; - } - - /// - /// Gets or sets the size of text display used by TMP. - /// - public Vector2 DisplaySize - { - get => Base.DisplaySize; - set => Base.DisplaySize = value; - } - - /// - /// Gets the arguments used while formatting the .
- /// Missing arguments for are not replaced and any extra arguments are ignored. - ///
- public SyncList Arguments => Base.Arguments; + public static new IReadOnlyCollection List => Dictionary.Values; /// public static TextToy Create(Transform? parent = null, bool networkSpawn = true) @@ -96,7 +48,9 @@ public static TextToy Create(Vector3 position, Quaternion rotation, Vector3 scal TextToy toy = Get(Create(position, rotation, scale, parent)); if (networkSpawn) + { toy.Spawn(); + } return toy; } @@ -110,7 +64,9 @@ public static TextToy Create(Vector3 position, Quaternion rotation, Vector3 scal public static TextToy? Get(BaseTextToy? baseTextToy) { if (baseTextToy == null) + { return null; + } return Dictionary.TryGetValue(baseTextToy, out TextToy item) ? item : (TextToy)CreateAdminToyWrapper(baseTextToy); } @@ -126,4 +82,58 @@ public static bool TryGet(BaseTextToy? baseTextToy, [NotNullWhen(true)] out Text textToy = Get(baseTextToy); return textToy != null; } + + /// + /// An internal constructor to prevent external instantiation. + /// + /// The base object. + internal TextToy(BaseTextToy baseToy) + : base(baseToy) + { + Base = baseToy; + + if (CanCache) + { + Dictionary.Add(baseToy, this); + } + } + + /// + /// The object. + /// + public new BaseTextToy Base { get; } + + /// + /// Gets or sets the base text format used when formatting the final text string.
+ /// Text can be formatted and arguments are replaced with . + ///
+ public string TextFormat + { + get => Base.TextFormat; + set => Base.TextFormat = value; + } + + /// + /// Gets or sets the size of text display used by TMP. + /// + public Vector2 DisplaySize + { + get => Base.DisplaySize; + set => Base.DisplaySize = value; + } + + /// + /// Gets the arguments used while formatting the .
+ /// Missing arguments for are not replaced and any extra arguments are ignored. + ///
+ public SyncList Arguments => Base.Arguments; + + /// + /// An internal method to remove itself from the cache when the base object is destroyed. + /// + internal override void OnRemove() + { + base.OnRemove(); + Dictionary.Remove(Base); + } } diff --git a/LabApi/Features/Wrappers/AdminToys/WaypointToy.cs b/LabApi/Features/Wrappers/AdminToys/WaypointToy.cs new file mode 100644 index 00000000..ff8733cd --- /dev/null +++ b/LabApi/Features/Wrappers/AdminToys/WaypointToy.cs @@ -0,0 +1,207 @@ +using System.Collections.Generic; +using System.Diagnostics.CodeAnalysis; +using UnityEngine; +using BaseWaypointToy = AdminToys.WaypointToy; + +namespace LabApi.Features.Wrappers; + +/// +/// Wrapper for the class. +/// +public class WaypointToy : AdminToy +{ + /// + /// Max distance in meters a waypoint can encapsulate along any dimension. + /// + public const float MaxBounds = BaseWaypointToy.MaxBounds; + + /// + /// Contains all the waypoint toys, accessible through their . + /// + public static new Dictionary Dictionary { get; } = []; + + /// + /// A reference to all instances of . + /// + public static new IReadOnlyCollection List => Dictionary.Values; + + /// + public static WaypointToy Create(Transform? parent = null, bool networkSpawn = true) + => Create(Vector3.zero, parent, networkSpawn); + + /// + public static WaypointToy Create(Vector3 position, Transform? parent = null, bool networkSpawn = true) + => Create(position, Quaternion.identity, parent, networkSpawn); + + /// + public static WaypointToy Create(Vector3 position, Quaternion rotation, Transform? parent = null, bool networkSpawn = true) + => Create(position, rotation, Vector3.one, parent, networkSpawn); + + /// + /// Creates a new waypoint toy. + /// + /// The initial local position. + /// The initial local rotation. + /// The initial local scale. + /// The parent transform. + /// Whether to spawn the toy on the client. + /// The created waypoint toy. + public static WaypointToy Create(Vector3 position, Quaternion rotation, Vector3 scale, Transform? parent = null, bool networkSpawn = true) + { + WaypointToy toy = Get(Create(position, rotation, scale, parent)); + + if (networkSpawn) + { + toy.Spawn(); + } + + return toy; + } + + /// + /// Gets the waypoint toy wrapper from the or creates a new one if it doesn't exist and the provided was not . + /// + /// The of the waypoint toy. + /// The requested waypoint toy or . + [return: NotNullIfNotNull(nameof(baseWaypointToy))] + public static WaypointToy? Get(BaseWaypointToy? baseWaypointToy) + { + if (baseWaypointToy == null) + { + return null; + } + + return Dictionary.TryGetValue(baseWaypointToy, out WaypointToy item) ? item : (WaypointToy)CreateAdminToyWrapper(baseWaypointToy); + } + + /// + /// Tries to get the waypoint toy wrapper from the . + /// + /// The of the waypoint toy. + /// The requested waypoint toy. + /// if the waypoint exists, otherwise . + public static bool TryGet(BaseWaypointToy? baseWaypointToy, [NotNullWhen(true)] out WaypointToy? waypointToy) + { + waypointToy = Get(baseWaypointToy); + return waypointToy != null; + } + + /// + /// An internal constructor to prevent external instantiation. + /// + /// The base object. + internal WaypointToy(BaseWaypointToy baseWaypointToy) + : base(baseWaypointToy) + { + Dictionary.Add(baseWaypointToy, this); + Base = baseWaypointToy; + } + + /// + /// The object. + /// + public new BaseWaypointToy Base { get; } + + /// + public override Vector3 Position + { + get => base.Position; + set + { + base.Position = value; + Base.UpdateWaypointChildren(); + } + } + + /// + public override Quaternion Rotation + { + get => base.Rotation; + set + { + base.Rotation = value; + Base.UpdateWaypointChildren(); + } + } + + /// + /// Gets or sets the scale on the waypoint toy. + /// Does not effect the bounds of the waypoint, use instead. + /// + /// + /// Scale can cause unindented side effects when used on a waypoint toy. + /// + public override Vector3 Scale + { + get => base.Scale; + set + { + base.Scale = value; + + if (value != Vector3.one) + { + Console.Logger.Warn("Setting scale on WaypointToy is not supported and may cause problems."); + } + } + } + + /// + /// Bounds the waypoint encapsulates along each dimension in meters. + /// Bounds is effected by position and rotation of the GameObject but not its scale. + /// Must not exceed Vector3.one * MaxBounds. + /// + /// + /// When is rotation and is not used, instead the bounds is axis aligned and its size is fixed at . + /// + public Vector3 BoundsSize + { + get => Base.BoundsSize; + set => Base.NetworkBoundsSize = value; + } + + /// + /// Gets or sets whether to visualize the waypoint's maximum bounds. + /// + public bool VisualizeBounds + { + get => Base.VisualizeBounds; + set => Base.NetworkVisualizeBounds = value; + } + + /// + /// Gets or sets how many meters to bias towards this waypoint. + /// + /// + /// The closest waypoint is determined by its square distance. + /// When set this takes away (Priority * Priority) from the sqr distance. + /// + public float PriorityBias + { + get => Base.Priority; + set => Base.NetworkPriority = value; + } + + /// + /// Force update all waypoint children to be up to date with the current position and rotation of the waypoint. + /// Call this when ever the waypoint is moved by a parent object or the waypoint is moved using base game APIs or external APIs. + /// + /// + /// Does not work if the waypoint is . + /// + public void UpdateWaypointChildren() => Base.UpdateWaypointChildren(); + + /// + public override string ToString() + { + return $"[WaypointToy: Position:{Position}, BoundsSize:{BoundsSize}, VisualizeBounds:{VisualizeBounds}, PriorityBias:{PriorityBias}]"; + } + + /// + /// An internal method to remove itself from the cache when the base object is destroyed. + /// + internal override void OnRemove() + { + base.OnRemove(); + Dictionary.Remove(Base); + } +} diff --git a/LabApi/Features/Wrappers/Facility/Announcer.cs b/LabApi/Features/Wrappers/Facility/Announcer.cs new file mode 100644 index 00000000..628dc96e --- /dev/null +++ b/LabApi/Features/Wrappers/Facility/Announcer.cs @@ -0,0 +1,277 @@ +using Cassie; +using Cassie.Interpreters; +using NorthwoodLib.Pools; +using PlayerRoles; +using PlayerStatsSystem; +using Respawning.NamingRules; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; + +namespace LabApi.Features.Wrappers; + +/// +/// The wrapper for in game CASSIE announcer. +/// +public static class Announcer +{ + /// + /// Gets whether CASSIE is currently speaking. + /// + public static bool IsSpeaking + => CassieAnnouncementDispatcher.CurrentAnnouncement != null; + + /// + /// Gets the line database for CASSIE. + /// + public static CassieLineDatabase? LineDatabase + => !CassieTtsAnnouncer.TryGetDatabase(out CassieLineDatabase db) ? null : db; + + /// + /// Gets all available voice lines for CASSIE. + /// + public static CassieLine[] AllLines + => LineDatabase ? LineDatabase.AllLines : []; + + /// + /// Gets all collection names in which voice lines are in. + /// + public static string[] CollectionNames + => AllLines.Select(static line => line.ApiName).Distinct().ToArray(); + + /// + /// Checks whether a specified word is valid for CASSIE. + /// String comparison is case-insensitive. + /// + /// The word to check. + /// Whether the word is valid. + public static bool IsValid(string word) + => CollectionNames.Any(line => line.Equals(word, StringComparison.InvariantCultureIgnoreCase)); + + /// + /// Calculates duration of specific message. + /// + /// The message. + /// Raw numbers. + /// The speed of the cassie talking. + /// Duration of the specific message in seconds. + [Obsolete("Use CalculateDuration(string message, CassiePlaybackModifiers playbackModifiers) instead.", true)] + public static float CalculateDuration(string message, bool rawNumber = false, float speed = 1f) + { + CassiePlaybackModifiers playbackModifiers = new() + { + Pitch = speed, + }; + return (float)CalculateDuration(message, playbackModifiers); + } + + /// + /// Calculates duration of specific message. + /// + /// The message. + /// The playback modifier. + /// Duration of the specific message in seconds. + public static double CalculateDuration(string message, CassiePlaybackModifiers playbackModifiers) + { + CalculateDuration(message, playbackModifiers, out double time); + return time; + } + + /// + /// Queues a custom announcement. + /// + /// The sentence CASSIE is supposed to say. + /// Sets a minimal 3-second moment of silence before the announcement. For most cases you wanna keep it true. + /// Whether the background noises play. + /// Show subtitles. + /// Custom subtitles to appear instead of the actual message. + [Obsolete("Use Message(string message, string customSubtitles = \"\", bool playBackground = true, float priority = 0f, float glitchScale = 1f) instead.", true)] + public static void Message(string message, bool isHeld = false, bool isNoisy = true, bool isSubtitles = true, string customSubtitles = "") + => Message(message, customSubtitles); + + /// + /// Queues a custom announcement. + /// + /// The sentence CASSIE is supposed to say. + /// Custom subtitles to play. + /// Should play the background track (bells, noise). + /// The priority of this message. The higher the value, the earlier it will be dequeued compared to lower-priority announcements. + /// Intensity of glitches and stutters added before sending to clients. + public static void Message(string message, string customSubtitles = "", bool playBackground = true, float priority = 0f, float glitchScale = 1f) + { + CassieTtsPayload payload = new(message, customSubtitles, playBackground); + Message(payload, priority, glitchScale); + } + + /// + /// Queues an cassie payload announcement. + /// + /// The payload to sent. + /// The priority of this message. The higher the value, the earlier it will be dequeued compared to lower-priority announcements. + /// Intensity of glitches and stutters added before sending to clients. Range from 0f to 1f. + public static void Message(CassieTtsPayload payload, float priority = 0f, float glitchScale = 1f) + { + CassieAnnouncement announcement = new(payload, priority, glitchScale); + CassieAnnouncementDispatcher.AddToQueue(announcement); + } + + /// + /// Plays the custom announcement with chance of 0f to 1f of adding a glitch or jam before each word. Values closer to 1f are higher chances. + /// + /// The sentence CASSIE is supposed to say. + /// The chance for glitch sound to be added before each word. Range from 0f to 1f. + /// The chance for jam sound to be added before each word. Range from 0f to 1f. + public static void GlitchyMessage(string message, float glitchChance, float jamChance) + { + message = CassieGlitchifier.Glitchify(message, glitchChance, jamChance); + Message(message, string.Empty, true, 0f, 0f); + } + + /// + /// Plays the termination announcement of a SCP player. If the specified player does not have an SCP role then nothing is played. + /// + /// The player who is being terminated as an SCP. + /// Damage handler causing the death of the player. + public static void ScpTermination(Player player, DamageHandlerBase info) + => CassieScpTerminationAnnouncement.AnnounceScpTermination(player.ReferenceHub, info); + + /// + /// Clears the CASSIE announcements queue. + /// + public static void Clear() + => CassieAnnouncementDispatcher.ClearAll(); + + /// + /// Converts player's team into CASSIE-able word. Unit names are converted into NATO_X words, followed by a number. For example "Alpha-5" is converted to "NATO_A 5". + /// + /// Target team. + /// MTF Unit name (for team ). + /// Converted name. + public static string ConvertTeam(Team team, string unitName) + { + string text = "CONTAINMENTUNIT UNKNOWN"; + switch (team) + { + case Team.FoundationForces: + { + if (!NamingRulesManager.TryGetNamingRule(team, out UnitNamingRule unitNamingRule)) + { + return text; + } + + string text2 = unitNamingRule.TranslateToCassie(unitName); + return "CONTAINMENTUNIT " + text2; + } + + case Team.ChaosInsurgency: + return "CHAOSINSURGENCY"; + case Team.Scientists: + return "SCIENCE PERSONNEL"; + case Team.ClassD: + return "CLASSD PERSONNEL"; + default: + return text; + } + } + + /// + /// Converts number into string. + /// + /// The number. + /// Number converted to string. + public static string ConvertNumber(int num) + { + if (LineDatabase == null) + { + return string.Empty; + } + + NumberInterpreter? numberInterpreter = (NumberInterpreter?)CassieTtsAnnouncer.Interpreters.FirstOrDefault(x => x is NumberInterpreter); + if (numberInterpreter == null) + { + return string.Empty; + } + + string word = num.ToString(); + + CassiePlaybackModifiers cassiePlaybackModifiers = default; + StringBuilder sb = StringBuilderPool.Shared.Rent(); + numberInterpreter.GetResults(LineDatabase, ref cassiePlaybackModifiers, word, sb, out bool halt); + + return StringBuilderPool.Shared.ToStringReturn(sb); + } + + /// + /// Converts player's into an SCP number identifier. + /// + /// The target . + /// The SCP number without spaces between. Used by CASSIE. + /// The SCP number with spaces between. Used by Subtitles. + public static void ConvertScp(RoleTypeId role, out string withoutSpace, out string withSpace) + => CassieScpTerminationAnnouncement.ConvertSCP(role, out withoutSpace, out withSpace); + + /// + /// Converts player's role name into an SCP number identifier. + /// + /// The targets role name. + /// The SCP number without spaces between. Used by CASSIE. + /// The SCP number with spaces between. Used by Subtitles. + public static void ConvertScp(string roleName, out string withoutSpace, out string withSpace) + => CassieScpTerminationAnnouncement.ConvertSCP(roleName, out withoutSpace, out withSpace); + + /// + /// Calculates duration of message. + /// + /// The remaining message. + /// The playback modifier. + /// The duration of the message. + public static void CalculateDuration(string remaining, CassiePlaybackModifiers modifiers, out double time) + => CalculateDuration(remaining.AsSpan(), modifiers, out time); + + /// + /// Calculates duration of message. + /// + /// The remaining message. + /// The playback modifier. + /// The duration of the message. + public static void CalculateDuration(ReadOnlySpan remaining, CassiePlaybackModifiers modifiers, out double time) + { + time = 0; + + if (LineDatabase == null) + { + return; + } + + int index = remaining.IndexOf(' '); + + StringBuilder sb = StringBuilderPool.Shared.Rent(); + + ReadOnlySpan word = index < 0 ? remaining : remaining[..index]; + + foreach (CassieInterpreter inter in CassieTtsAnnouncer.Interpreters) + { + List results = inter.GetResults(LineDatabase, ref modifiers, word, sb, out bool jobDone); + + time += results.Sum(static result => result.Modifiers.GetTimeUntilNextWord(result.Line)); + + if (jobDone) + { + // The interpreter claims there's no need to process the word by other interpreters. + break; + } + } + + StringBuilderPool.Shared.Return(sb); + + if (index < 0) + { + return; + } + + remaining = remaining[(index + 1)..]; + CalculateDuration(remaining, modifiers, out double timeOut); + time += timeOut; + } +} \ No newline at end of file diff --git a/LabApi/Features/Wrappers/Facility/Cassie.cs b/LabApi/Features/Wrappers/Facility/Cassie.cs index 79d267e8..e9319d71 100644 --- a/LabApi/Features/Wrappers/Facility/Cassie.cs +++ b/LabApi/Features/Wrappers/Facility/Cassie.cs @@ -1,106 +1,101 @@ -using PlayerRoles; +using Cassie; +using PlayerRoles; using PlayerStatsSystem; -using Respawning; using System; -using System.Linq; -using static NineTailedFoxAnnouncer; namespace LabApi.Features.Wrappers; -/// -/// The wrapper for in game Cassie announcer. -/// +/// +[Obsolete("Use Announcer instead of Cassie.", true)] public static class Cassie { - /// - /// Gets whether Cassie is currently speaking. - /// - public static bool IsSpeaking => singleton.queue.Count != 0; - - /// - /// Gets all available voice lines for Cassie. - /// - public static VoiceLine[] AllLines => singleton.voiceLines; - - /// - /// Gets all collection names in which voicelines are in. - /// - public static string[] CollectionNames => singleton.voiceLines.Select(n => n.collection).Distinct().ToArray(); - - /// - /// Checks whether a specified word is valid for cassie. - /// String comparison is case-insensitive. - /// - /// The word to check. - /// Whether the word is valid. - public static bool IsValid(string word) => singleton.voiceLines.Any(line => line.apiName.Equals(word, StringComparison.InvariantCultureIgnoreCase)); - - /// - /// Calculates duration of specific message. - /// - /// The message. - /// Raw numbers. - /// Duration of the specific message in seconds. - public static float CalculateDuration(string message, bool rawNumber = false, float speed = 1f) => singleton.CalculateDuration(message, rawNumber, speed); - - /// - /// Plays a custom announcement. - /// - /// The sentence Cassie is supposed to say. - /// Sets a minimal 3-second moment of silence before the announcement. For most cases you wanna keep it true. - /// Whether the background noises play. - /// Show subtitles. - /// Custom subtitles to appear instead of the actual message. - public static void Message(string message, bool isHeld = false, bool isNoisy = true, bool isSubtitles = true, string customSubtitles = "") => RespawnEffectsController.PlayCassieAnnouncement(message, isHeld, isNoisy, isSubtitles, customSubtitles); - - /// - /// Plays the custom announcement with chance of 0f to 1f of adding a glitch or jam before each word. Values closer to 1f are higher chances. - /// - /// The sentence Cassie is supposed to say. - /// The chance for glitch sound to be added before each word. Range from 0f to 1f. - /// The chance for jam sound to be added before each word. Range from 0f to 1f. - public static void GlitchyMessage(string message, float glitchChance, float jamChance) => singleton.ServerOnlyAddGlitchyPhrase(message, glitchChance, jamChance); - - /// - /// Plays the termination announcement of a SCP player. If the specified player does not have an SCP role then nothing is played. - /// - /// The player who is being terminated as an SCP. - /// Damage handler causing the death of the player. - public static void ScpTermination(Player player, DamageHandlerBase info) => AnnounceScpTermination(player.ReferenceHub, info); - - /// - /// Clears the Cassie announcements queue. - /// - public static void Clear() => singleton.ClearQueue(); - - /// - /// Converts player's team into Cassie-able word. Unit names are converted into NATO_X words, followed by a number. For example "Alpha-5" is converted to "NATO_A 5". - /// - /// Target team. - /// MTF Unit name (for team ). - /// Converted name. - public static string ConvertTeam(Team team, string unitName) => NineTailedFoxAnnouncer.ConvertTeam(team, unitName); - - /// - /// Converts number into string. - /// - /// The number. - /// Number converted to string. - public static string ConvertNumber(int num) => NineTailedFoxAnnouncer.ConvertNumber(num); - - /// - /// Converts player's into an SCP number identifier. - /// - /// The target . - /// The SCP number without spaces between. Used by Cassie. - /// The SCP number with spaces between. Used by Subtitles. - public static void ConvertScp(RoleTypeId role, out string withoutSpace, out string withSpace) => NineTailedFoxAnnouncer.ConvertSCP(role, out withoutSpace, out withSpace); - - /// - /// Converts player's role name into an SCP number identifier. - /// - /// The targets role name - /// The SCP number without spaces between. Used by Cassie. - /// The SCP number with spaces between. Used by Subtitles. - public static void ConvertScp(string roleName, out string withoutSpace, out string withSpace) => NineTailedFoxAnnouncer.ConvertSCP(roleName, out withoutSpace, out withSpace); + /// + [Obsolete("Use Announcer.IsSpeaking instead.", true)] + public static bool IsSpeaking + => Announcer.IsSpeaking; + + /// + [Obsolete("Use Announcer.LineDatabase instead.", true)] + public static CassieLineDatabase? LineDatabase + => Announcer.LineDatabase; + + /// + [Obsolete("Use Announcer.AllLines instead.", true)] + public static CassieLine[] AllLines + => Announcer.AllLines; + + /// + [Obsolete("Use Announcer.CollectionNames instead.", true)] + public static string[] CollectionNames + => Announcer.CollectionNames; + + /// + [Obsolete("Use Announcer.IsValid(string) instead.", true)] + public static bool IsValid(string word) + => Announcer.IsValid(word); + + /// + [Obsolete("Use Announcer.CalculateDuration(string message, CassiePlaybackModifiers playbackModifiers) instead.", true)] + public static float CalculateDuration(string message, bool rawNumber = false, float speed = 1f) + => Announcer.CalculateDuration(message, rawNumber, speed); + + /// + [Obsolete("Use Announcer.CalculateDuration(string, CassiePlaybackModifiers) instead.", true)] + public static double CalculateDuration(string message, CassiePlaybackModifiers playbackModifiers) + => Announcer.CalculateDuration(message, playbackModifiers); + + /// + [Obsolete("Use Announcer.Message(string message, string customSubtitles = \"\", bool playBackground = true, float priority = 0f, float glitchScale = 1f) instead.", true)] + public static void Message(string message, bool isHeld = false, bool isNoisy = true, bool isSubtitles = true, string customSubtitles = "") + => Announcer.Message(message, customSubtitles); + + /// + [Obsolete("Use Announcer.Message(string, string, bool, float, float) instead.", true)] + public static void Message(string message, string customSubtitles = "", bool playBackground = true, float priority = 0f, float glitchScale = 1f) + => Announcer.Message(message, customSubtitles, playBackground, priority, glitchScale); + + /// + [Obsolete("Use Announcer.Message(CassieTtsPayload, float, float) instead.", true)] + public static void Message(CassieTtsPayload payload, float priority = 0f, float glitchScale = 1f) + => Announcer.Message(payload, priority, glitchScale); + + /// + [Obsolete("Use Announcer.GlitchyMessage(string, float, float) instead.", true)] + public static void GlitchyMessage(string message, float glitchChance, float jamChance) + => Announcer.GlitchyMessage(message, glitchChance, jamChance); + + /// + [Obsolete("Use Announcer.ScpTermination(Player, DamageHandlerBase) instead.", true)] + public static void ScpTermination(Player player, DamageHandlerBase info) + => Announcer.ScpTermination(player, info); + + /// + [Obsolete("Use Announcer.Clear() instead.", true)] + public static void Clear() + => Announcer.Clear(); + + /// + [Obsolete("Use Announcer.ConvertTeam(Team, string) instead.", true)] + public static string ConvertTeam(Team team, string unitName) + => Announcer.ConvertTeam(team, unitName); + + /// + [Obsolete("Use Announcer.ConvertNumber(int) instead.", true)] + public static string ConvertNumber(int num) + => Announcer.ConvertNumber(num); + + /// + [Obsolete("Use Announcer.ConvertScp(RoleTypeId, out string, out string) instead.", true)] + public static void ConvertScp(RoleTypeId role, out string withoutSpace, out string withSpace) + => Announcer.ConvertScp(role, out withoutSpace, out withSpace); + + /// + [Obsolete("Use Announcer.ConvertScp(string, out string, out string) instead.", true)] + public static void ConvertScp(string roleName, out string withoutSpace, out string withSpace) + => Announcer.ConvertScp(roleName, out withoutSpace, out withSpace); + + /// + [Obsolete("Use Announcer.CalculateDuration(ReadOnlySpan{char}, CassiePlaybackModifiers, out double) instead.", true)] + public static void CalculateDuration(ReadOnlySpan remaining, CassiePlaybackModifiers modifiers, out double time) + => Announcer.CalculateDuration(remaining, modifiers, out time); } \ No newline at end of file diff --git a/LabApi/Features/Wrappers/Facility/Decontamination.cs b/LabApi/Features/Wrappers/Facility/Decontamination.cs index e752786f..5c048120 100644 --- a/LabApi/Features/Wrappers/Facility/Decontamination.cs +++ b/LabApi/Features/Wrappers/Facility/Decontamination.cs @@ -13,16 +13,7 @@ public static class Decontamination public static DecontaminationStatus Status { get => Singleton.DecontaminationOverride; - set - { - if (value == DecontaminationStatus.Forced) - { - Singleton.ForceDecontamination(); - return; - } - - Singleton.DecontaminationOverride = value; - } + set => Singleton.DecontaminationOverride = value; } /// @@ -31,7 +22,7 @@ public static DecontaminationStatus Status public static bool IsDecontaminating => Singleton.IsDecontaminating; /// - /// Gets the current server time since round has started plus the + /// Gets the current server time since round has started plus the . /// public static double ServerTime => GetServerTime; diff --git a/LabApi/Features/Wrappers/Facility/Doors/BreakableDoor.cs b/LabApi/Features/Wrappers/Facility/Doors/BreakableDoor.cs index 03d0d0f3..47066280 100644 --- a/LabApi/Features/Wrappers/Facility/Doors/BreakableDoor.cs +++ b/LabApi/Features/Wrappers/Facility/Doors/BreakableDoor.cs @@ -13,12 +13,33 @@ public class BreakableDoor : Door /// /// Contains all the cached instances, accessible through their . /// - public new static Dictionary Dictionary { get; } = []; + public static new Dictionary Dictionary { get; } = []; /// /// A reference to all instances currently in the game. /// - public new static IReadOnlyCollection List => Dictionary.Values; + public static new IReadOnlyCollection List => Dictionary.Values; + + /// + /// Gets the wrapper from the , or creates a new one if it doesn't exist. + /// + /// The of the door. + /// The requested door wrapper or null if the input was null. + [return: NotNullIfNotNull(nameof(baseBreakableDoor))] + public static BreakableDoor? Get(BaseBreakableDoor? baseBreakableDoor) + { + if (baseBreakableDoor == null) + { + return null; + } + + if (Dictionary.TryGetValue(baseBreakableDoor, out BreakableDoor door)) + { + return door; + } + + return (BreakableDoor)CreateDoorWrapper(baseBreakableDoor); + } /// /// An internal constructor to prevent external instantiation. @@ -27,17 +48,12 @@ public class BreakableDoor : Door internal BreakableDoor(BaseBreakableDoor baseBreakableDoor) : base(baseBreakableDoor) { - Dictionary.Add(baseBreakableDoor, this); Base = baseBreakableDoor; - } - /// - /// An internal method to remove itself from the cache when the base object is destroyed. - /// - internal override void OnRemove() - { - base.OnRemove(); - Dictionary.Remove(Base); + if (CanCache) + { + Dictionary.Add(baseBreakableDoor, this); + } } /// @@ -118,19 +134,11 @@ public bool TryBreak(DoorDamageType type = DoorDamageType.ServerCommand) public bool TryRepair() => Base.ServerRepair(); /// - /// Gets the wrapper from the , or creates a new one if it doesn't exist. + /// An internal method to remove itself from the cache when the base object is destroyed. /// - /// The of the door. - /// The requested door wrapper or null if the input was null. - [return: NotNullIfNotNull(nameof(baseBreakableDoor))] - public static BreakableDoor? Get(BaseBreakableDoor? baseBreakableDoor) + internal override void OnRemove() { - if (baseBreakableDoor == null) - return null; - - if (Dictionary.TryGetValue(baseBreakableDoor, out BreakableDoor door)) - return door; - - return (BreakableDoor)CreateDoorWrapper(baseBreakableDoor); + base.OnRemove(); + Dictionary.Remove(Base); } } diff --git a/LabApi/Features/Wrappers/Facility/Doors/BulkheadDoor.cs b/LabApi/Features/Wrappers/Facility/Doors/BulkheadDoor.cs index e9d46f47..e4d5edb3 100644 --- a/LabApi/Features/Wrappers/Facility/Doors/BulkheadDoor.cs +++ b/LabApi/Features/Wrappers/Facility/Doors/BulkheadDoor.cs @@ -13,12 +13,33 @@ public class BulkheadDoor : Gate /// /// Contains all the cached instances, accessible through their . /// - public new static Dictionary Dictionary { get; } = []; + public static new Dictionary Dictionary { get; } = []; /// /// A reference to all instances currently in the game. /// - public new static IReadOnlyCollection List => Dictionary.Values; + public static new IReadOnlyCollection List => Dictionary.Values; + + /// + /// Gets the wrapper from the , or creates a new one if it doesn't exist. + /// + /// The of the door. + /// The requested door wrapper or null if the input was null. + [return: NotNullIfNotNull(nameof(pryableDoor))] + public static new BulkheadDoor? Get(PryableDoor? pryableDoor) + { + if (pryableDoor == null) + { + return null; + } + + if (Dictionary.TryGetValue(pryableDoor, out BulkheadDoor door)) + { + return door; + } + + return (BulkheadDoor)CreateDoorWrapper(pryableDoor); + } /// /// An internal constructor to prevent external instantiation. @@ -27,20 +48,17 @@ public class BulkheadDoor : Gate internal BulkheadDoor(PryableDoor pryableDoor) : base(pryableDoor) { - Dictionary.Add(pryableDoor, this); Base = pryableDoor; DoorCrusherExtension extension = pryableDoor.gameObject.GetComponent(); if (extension != null) + { Crusher = new DoorCrusher(extension); - } + } - /// - /// An internal method to remove itself from the cache when the base object is destroyed. - /// - internal override void OnRemove() - { - base.OnRemove(); - Dictionary.Remove(Base); + if (CanCache) + { + Dictionary.Add(pryableDoor, this); + } } /// @@ -57,19 +75,11 @@ internal override void OnRemove() public DoorCrusher? Crusher { get; } /// - /// Gets the wrapper from the , or creates a new one if it doesn't exist. + /// An internal method to remove itself from the cache when the base object is destroyed. /// - /// The of the door. - /// The requested door wrapper or null if the input was null. - [return: NotNullIfNotNull(nameof(pryableDoor))] - public new static BulkheadDoor? Get(PryableDoor? pryableDoor) + internal override void OnRemove() { - if (pryableDoor == null) - return null; - - if (Dictionary.TryGetValue(pryableDoor, out BulkheadDoor door)) - return door; - - return (BulkheadDoor)CreateDoorWrapper(pryableDoor); + base.OnRemove(); + Dictionary.Remove(Base); } } diff --git a/LabApi/Features/Wrappers/Facility/Doors/CheckpointDoor.cs b/LabApi/Features/Wrappers/Facility/Doors/CheckpointDoor.cs index 4eeff4bd..d2f58955 100644 --- a/LabApi/Features/Wrappers/Facility/Doors/CheckpointDoor.cs +++ b/LabApi/Features/Wrappers/Facility/Doors/CheckpointDoor.cs @@ -15,12 +15,33 @@ public class CheckpointDoor : Door /// /// Contains all the cached instances, accessible through their . /// - public new static Dictionary Dictionary { get; } = []; + public static new Dictionary Dictionary { get; } = []; /// /// A reference to all instances currently in the game. /// - public new static IReadOnlyCollection List => Dictionary.Values; + public static new IReadOnlyCollection List => Dictionary.Values; + + /// + /// Gets the wrapper from the , or creates a new one if it doesn't exist. + /// + /// The of the door. + /// The requested door wrapper or null if the input was null. + [return: NotNullIfNotNull(nameof(baseCheckpointDoor))] + public static CheckpointDoor? Get(BaseCheckpointDoor? baseCheckpointDoor) + { + if (baseCheckpointDoor == null) + { + return null; + } + + if (Dictionary.TryGetValue(baseCheckpointDoor, out CheckpointDoor door)) + { + return door; + } + + return (CheckpointDoor)CreateDoorWrapper(baseCheckpointDoor); + } /// /// An internal constructor to prevent external instantiation. @@ -29,21 +50,18 @@ public class CheckpointDoor : Door internal CheckpointDoor(BaseCheckpointDoor baseCheckpointDoor) : base(baseCheckpointDoor) { - Dictionary.Add(baseCheckpointDoor, this); Base = baseCheckpointDoor; SubDoors = new Door[baseCheckpointDoor.SubDoors.Length]; for (int i = 0; i < baseCheckpointDoor.SubDoors.Length; i++) + { SubDoors[i] = Get(baseCheckpointDoor.SubDoors[i]); - } + } - /// - /// An internal method to remove itself from the cache when the base object is destroyed. - /// - internal override void OnRemove() - { - base.OnRemove(); - Dictionary.Remove(Base); + if (CanCache) + { + Dictionary.Add(baseCheckpointDoor, this); + } } /// @@ -155,19 +173,11 @@ public bool TryBreak(DoorDamageType type = DoorDamageType.ServerCommand) => TryDamage(float.MaxValue, type); /// - /// Gets the wrapper from the , or creates a new one if it doesn't exist. + /// An internal method to remove itself from the cache when the base object is destroyed. /// - /// The of the door. - /// The requested door wrapper or null if the input was null. - [return: NotNullIfNotNull(nameof(baseCheckpointDoor))] - public static CheckpointDoor? Get(BaseCheckpointDoor? baseCheckpointDoor) + internal override void OnRemove() { - if (baseCheckpointDoor == null) - return null; - - if (Dictionary.TryGetValue(baseCheckpointDoor, out CheckpointDoor door)) - return door; - - return (CheckpointDoor)CreateDoorWrapper(baseCheckpointDoor); + base.OnRemove(); + Dictionary.Remove(Base); } } diff --git a/LabApi/Features/Wrappers/Facility/Doors/Door.cs b/LabApi/Features/Wrappers/Facility/Doors/Door.cs index 6e2c6ff5..03e8e6c5 100644 --- a/LabApi/Features/Wrappers/Facility/Doors/Door.cs +++ b/LabApi/Features/Wrappers/Facility/Doors/Door.cs @@ -17,31 +17,15 @@ namespace LabApi.Features.Wrappers; /// public class Door { - [InitializeWrapper] - internal static void Initialize() - { - DoorVariant.OnInstanceCreated += OnAdded; - DoorVariant.OnInstanceRemoved += OnRemoved; - - Register(x => new BreakableDoor(x)); - Register(x => new ElevatorDoor(x)); - Register(x => new Timed173Gate(x)); - Register(x => x.name.StartsWith("HCZ BulkDoor") ? new BulkheadDoor(x) : new Gate(x)); - Register(x => new NonInteractableDoor(x)); - Register(x => new CheckpointDoor(x)); - Register(x => new DummyDoor(x)); - Register(x => new Door(x)); - } - /// /// Contains all the handlers for constructing wrappers for the associated base game types. /// - private static readonly Dictionary> typeWrappers = []; + private static readonly Dictionary> TypeWrappers = []; /// /// Contains all the values for the associated . /// - private static readonly Dictionary doorNameDictionary = new() + private static readonly Dictionary DoorNameDictionary = new() { { "LCZ_CAFE", DoorName.LczPc }, { "LCZ_WC", DoorName.LczWc }, @@ -67,6 +51,7 @@ internal static void Initialize() { "HID_CHAMBER", DoorName.HczHidChamber }, { "HID_UPPER", DoorName.HczHidUpper }, { "HID_LOWER", DoorName.HczHidLower }, + { "HID_LAB", DoorName.HczHidChamber }, { "NUKE_ARMORY", DoorName.HczNukeArmory }, { "106_PRIMARY", DoorName.Hcz106Primiary }, { "106_SECONDARY", DoorName.Hcz106Secondary }, @@ -79,18 +64,155 @@ internal static void Initialize() { "SURFACE_NUKE", DoorName.SurfaceNuke }, { "ESCAPE_PRIMARY", DoorName.SurfaceEscapePrimary }, { "ESCAPE_SECONDARY", DoorName.SurfaceEscapeSecondary }, - { "ESCAPE_FINAL", DoorName.SurfaceEscapeFinal } + { "ESCAPE_FINAL", DoorName.SurfaceEscapeFinal }, }; + /// + /// A reference to all instances currently in the game. + /// + public static IReadOnlyCollection List => Dictionary.Values; + /// /// Contains all the cached doors in the game, accessible through their . /// protected static Dictionary Dictionary { get; } = []; /// - /// A reference to all instances currently in the game. + /// Gets the door wrapper from the , or creates a new one if it doesn't exist. /// - public static IReadOnlyCollection List => Dictionary.Values; + /// The of the door. + /// The requested door or null if the input was null. + [return: NotNullIfNotNull(nameof(doorVariant))] + public static Door? Get(DoorVariant? doorVariant) + { + if (doorVariant == null) + { + return null; + } + + if (Dictionary.TryGetValue(doorVariant, out Door door)) + { + return door; + } + + return CreateDoorWrapper(doorVariant); + } + + /// + /// Gets the door by it's nametag. + /// + /// The door's nametag. + /// The requested door. May be null if door with provided nametag does not exist. + public static Door? Get(string nametag) + { + if (!DoorNametagExtension.NamedDoors.TryGetValue(nametag, out DoorNametagExtension doorNametagExtension)) + { + return null; + } + + return Get(doorNametagExtension.TargetDoor); + } + + /// + /// Gets the door in specified zone. + /// + /// Target zone. + /// An enumerable set of doors. + public static IEnumerable Get(FacilityZone facilityZone) => + List.Where(x => x.Rooms.First().Zone.Equals(facilityZone)); + + /// + /// Gets the door in specified room. + /// + /// Target room wrapper. + /// An enumerable set of doors. + public static IEnumerable Get(Room roomId) => Get(roomId.Base); + + /// + /// Gets the door in specified room. + /// + /// Target room identifier. + /// An enumerable set of doors. + public static IEnumerable Get(RoomIdentifier roomId) => + List.Where(x => x.Rooms.First().Equals(roomId)); + + /// + /// Initializes the door wrapper class. + /// + [InitializeWrapper] + internal static void Initialize() + { + DoorVariant.OnInstanceCreated += OnAdded; + DoorVariant.OnInstanceRemoved += OnRemoved; + + Register(x => new BreakableDoor(x)); + Register(x => new ElevatorDoor(x)); + Register(x => new Timed173Gate(x)); + Register(x => x.name.StartsWith("HCZ BulkDoor") ? new BulkheadDoor(x) : new Gate(x)); + Register(x => new NonInteractableDoor(x)); + Register(x => new CheckpointDoor(x)); + Register(x => new DummyDoor(x)); + Register(x => new Door(x)); + } + + /// + /// A protected method to create new door wrappers from the base game object. + /// + /// The base object to create the wrapper from. + /// The newly created wrapper. + protected static Door CreateDoorWrapper(DoorVariant doorVariant) + { + Type targetType = doorVariant.GetType(); + if (!TypeWrappers.TryGetValue(targetType, out Func ctorFunc)) + { + Logger.Warn($"Unable to find {nameof(Door)} wrapper for {targetType.Name}, backup up to base constructor!"); + return new Door(doorVariant); + } + + return ctorFunc.Invoke(doorVariant); + } + + /// + /// Private method to handle the creation of new doors in the server. + /// + /// The that was created. + private static void OnAdded(DoorVariant doorVariant) + { + try + { + if (!Dictionary.ContainsKey(doorVariant)) + { + CreateDoorWrapper(doorVariant); + } + } + catch (Exception ex) + { + Console.Logger.Error($"An exception occurred while handling the creation of a new door in LabApi.Features.Wrappers.Door.OnAdded(DoorVariant). Error: {ex}"); + } + } + + /// + /// Private method to handle the removal of doors from the server. + /// + /// The door being destroyed. + private static void OnRemoved(DoorVariant doorVariant) + { + if (Dictionary.TryGetValue(doorVariant, out Door door)) + { + door.OnRemove(); + } + } + + /// + /// A private method to handle the addition of wrapper handlers. + /// + /// The derived base game type to handle. + /// A handler to construct the wrapper with the base game instance. + private static void Register(Func constructor) + where T : DoorVariant + { + TypeWrappers.Add(typeof(T), x => constructor((T)x)); + } /// /// A private constructor to prevent external instantiation. @@ -98,25 +220,30 @@ internal static void Initialize() /// The of the door. protected Door(DoorVariant doorVariant) { - Dictionary.Add(doorVariant, this); Base = doorVariant; + if (CanCache) + { + Dictionary.Add(doorVariant, this); + } + if (doorVariant.TryGetComponent(out DoorNametagExtension nametag) && !string.IsNullOrEmpty(nametag.GetName)) { - if (doorNameDictionary.TryGetValue(nametag.GetName, out DoorName doorName)) + if (DoorNameDictionary.TryGetValue(nametag.GetName, out DoorName doorName)) + { DoorName = doorName; + } else - Logger.Warn($"Missing DoorName enum value for door name tag {nametag.GetName}"); + { + Logger.InternalWarn($"Missing DoorName enum value for door name tag {nametag.GetName}"); + } } } /// - /// An internal virtual method to signal that the base object has been destroyed. + /// Whether the door has been destroyed, see . /// - internal virtual void OnRemove() - { - Dictionary.Remove(Base); - } + public bool IsDestroyed => Base == null; /// /// The base object. @@ -142,7 +269,19 @@ internal virtual void OnRemove() /// /// Gets the rooms which have this door. /// - public Room[] Rooms => Base.Rooms.Select(Room.Get).ToArray(); + public Room[] Rooms + { + get + { + // Sometimes the Rooms can be null. (When registering checkpoint SubDoors) + if (Base.Rooms == null) + { + return []; + } + + return Base.Rooms.Select(Room.Get).ToArray()!; + } + } /// /// Gets the zone in which this door is. @@ -182,17 +321,10 @@ public bool IsLocked } /// - /// Gets the door's + /// Gets the door's . /// public DoorLockReason LockReason => (DoorLockReason)Base.ActiveLocks; - /// - /// Locks the door. - /// - /// The reason. - /// Whether the door lock reason is new. - public void Lock(DoorLockReason reason, bool enabled) => Base.ServerChangeLock(reason, enabled); - /// /// Gets or sets the required . /// @@ -231,6 +363,18 @@ public bool Bypass2176 /// public Quaternion Rotation => Transform.rotation; + /// + /// Whether the wrapper can be cached. + /// + protected bool CanCache => !IsDestroyed && Base.isActiveAndEnabled; + + /// + /// Locks the door. + /// + /// The reason. + /// Whether the door lock reason is new. + public void Lock(DoorLockReason reason, bool enabled) => Base.ServerChangeLock(reason, enabled); + /// /// Plays a sound that indicates that lock bypass was denied. /// @@ -248,106 +392,10 @@ public override string ToString() } /// - /// Gets the door wrapper from the , or creates a new one if it doesn't exist. - /// - /// The of the door. - /// The requested door or null if the input was null. - [return: NotNullIfNotNull(nameof(doorVariant))] - public static Door? Get(DoorVariant? doorVariant) - { - if (doorVariant == null) - return null; - - if (Dictionary.TryGetValue(doorVariant, out Door door)) - return door; - - return CreateDoorWrapper(doorVariant); - } - - /// - /// Gets the door by it's nametag. - /// - /// The door's nametag - /// The requested door. May be null if door with provided nametag does not exist. - public static Door? Get(string nametag) - { - if (!DoorNametagExtension.NamedDoors.TryGetValue(nametag, out DoorNametagExtension doorNametagExtension)) - return null; - - return Get(doorNametagExtension.TargetDoor); - } - - /// - /// Gets the door in specified zone. - /// - /// Target zone. - public static IEnumerable Get(FacilityZone facilityZone) => - List.Where(x => x.Rooms.First().Zone.Equals(facilityZone)); - - /// - /// Gets the door in specified room. - /// - /// Target room wrapper. - public static IEnumerable Get(Room roomId) => Get(roomId.Base); - - /// - /// Gets the door in specified room. - /// - /// Target room identifier. - public static IEnumerable Get(RoomIdentifier roomId) => - List.Where(x => x.Rooms.First().Equals(roomId)); - - /// - /// A protected method to create new door wrappers from the base game object. - /// - /// The base object to create the wrapper from. - /// The newly created wrapper. - protected static Door CreateDoorWrapper(DoorVariant doorVariant) - { - Type targetType = doorVariant.GetType(); - if (!typeWrappers.TryGetValue(targetType, out Func ctorFunc)) - { - Logger.Warn($"Unable to find {nameof(Door)} wrapper for {targetType.Name}, backup up to base constructor!"); - return new Door(doorVariant); - } - - return ctorFunc.Invoke(doorVariant); - } - - /// - /// Private method to handle the creation of new doors in the server. - /// - /// The that was created. - private static void OnAdded(DoorVariant doorVariant) - { - try - { - if (!Dictionary.ContainsKey(doorVariant)) - CreateDoorWrapper(doorVariant); - } - catch (Exception ex) - { - Console.Logger.Error($"An exception occurred while handling the creation of a new door in LabApi.Features.Wrappers.Door.OnAdded(DoorVariant). Error: {ex}"); - } - } - - /// - /// Private method to handle the removal of doors from the server. - /// - /// The door being destroyed. - private static void OnRemoved(DoorVariant doorVariant) - { - if (Dictionary.TryGetValue(doorVariant, out Door door)) - door.OnRemove(); - } - - /// - /// A private method to handle the addition of wrapper handlers. + /// An internal virtual method to signal that the base object has been destroyed. /// - /// The derived base game type to handle. - /// A handler to construct the wrapper with the base game instance. - private static void Register(Func constructor) where T : DoorVariant + internal virtual void OnRemove() { - typeWrappers.Add(typeof(T), x => constructor((T)x)); + Dictionary.Remove(Base); } -} \ No newline at end of file +} diff --git a/LabApi/Features/Wrappers/Facility/Doors/DummyDoor.cs b/LabApi/Features/Wrappers/Facility/Doors/DummyDoor.cs index e9947feb..a31cebe9 100644 --- a/LabApi/Features/Wrappers/Facility/Doors/DummyDoor.cs +++ b/LabApi/Features/Wrappers/Facility/Doors/DummyDoor.cs @@ -12,12 +12,33 @@ public class DummyDoor : Door /// /// Contains all the cached instances, accessible through their . /// - public new static Dictionary Dictionary { get; } = []; + public static new Dictionary Dictionary { get; } = []; /// /// A reference to all instances currently in the game. /// - public new static IReadOnlyCollection List => Dictionary.Values; + public static new IReadOnlyCollection List => Dictionary.Values; + + /// + /// Gets the wrapper from the , or creates a new one if it doesn't exist. + /// + /// The of the door. + /// The requested door wrapper or null if the input was null. + [return: NotNullIfNotNull(nameof(baseDummyDoor))] + public static DummyDoor? Get(BaseDummyDoor? baseDummyDoor) + { + if (baseDummyDoor == null) + { + return null; + } + + if (Dictionary.TryGetValue(baseDummyDoor, out DummyDoor door)) + { + return door; + } + + return (DummyDoor)CreateDoorWrapper(baseDummyDoor); + } /// /// An internal constructor to prevent external instantiation. @@ -30,34 +51,17 @@ internal DummyDoor(BaseDummyDoor baseDummyDoor) Base = baseDummyDoor; } - /// - /// An internal method to remove itself from the cache when the base object is destroyed. - /// - internal override void OnRemove() - { - base.OnRemove(); - Dictionary.Remove(Base); - } - /// /// The base object. /// public new BaseDummyDoor Base { get; } /// - /// Gets the wrapper from the , or creates a new one if it doesn't exist. + /// An internal method to remove itself from the cache when the base object is destroyed. /// - /// The of the door. - /// The requested door wrapper or null if the input was null. - [return: NotNullIfNotNull(nameof(baseDummyDoor))] - public static DummyDoor? Get(BaseDummyDoor? baseDummyDoor) + internal override void OnRemove() { - if (baseDummyDoor == null) - return null; - - if (Dictionary.TryGetValue(baseDummyDoor, out DummyDoor door)) - return door; - - return (DummyDoor)CreateDoorWrapper(baseDummyDoor); + base.OnRemove(); + Dictionary.Remove(Base); } } diff --git a/LabApi/Features/Wrappers/Facility/Doors/ElevatorDoor.cs b/LabApi/Features/Wrappers/Facility/Doors/ElevatorDoor.cs index b0e586b8..9021e7d4 100644 --- a/LabApi/Features/Wrappers/Facility/Doors/ElevatorDoor.cs +++ b/LabApi/Features/Wrappers/Facility/Doors/ElevatorDoor.cs @@ -14,12 +14,33 @@ public class ElevatorDoor : Door /// /// Contains all the cached instances, accessible through their . /// - public new static Dictionary Dictionary { get; } = []; + public static new Dictionary Dictionary { get; } = []; /// /// A reference to all instances currently in the game. /// - public new static IReadOnlyCollection List => Dictionary.Values; + public static new IReadOnlyCollection List => Dictionary.Values; + + /// + /// Gets the wrapper from the , or creates a new one if it doesn't exist. + /// + /// The of the door. + /// The requested door wrapper or null if the input was null. + [return: NotNullIfNotNull(nameof(baseElevatorDoor))] + public static ElevatorDoor? Get(BaseElevatorDoor? baseElevatorDoor) + { + if (baseElevatorDoor == null) + { + return null; + } + + if (Dictionary.TryGetValue(baseElevatorDoor, out ElevatorDoor door)) + { + return door; + } + + return (ElevatorDoor)CreateDoorWrapper(baseElevatorDoor); + } /// /// An internal constructor to prevent external instantiation. @@ -28,17 +49,12 @@ public class ElevatorDoor : Door internal ElevatorDoor(BaseElevatorDoor baseElevatorDoor) : base(baseElevatorDoor) { - Dictionary.Add(baseElevatorDoor, this); Base = baseElevatorDoor; - } - /// - /// An internal method to remove itself from the cache when the base object is destroyed. - /// - internal override void OnRemove() - { - base.OnRemove(); - Dictionary.Remove(Base); + if (CanCache) + { + Dictionary.Add(baseElevatorDoor, this); + } } /// @@ -57,19 +73,11 @@ internal override void OnRemove() public ElevatorGroup Group => Base.Group; /// - /// Gets the wrapper from the , or creates a new one if it doesn't exist. + /// An internal method to remove itself from the cache when the base object is destroyed. /// - /// The of the door. - /// The requested door wrapper or null if the input was null. - [return: NotNullIfNotNull(nameof(baseElevatorDoor))] - public static ElevatorDoor? Get(BaseElevatorDoor? baseElevatorDoor) + internal override void OnRemove() { - if (baseElevatorDoor == null) - return null; - - if (Dictionary.TryGetValue(baseElevatorDoor, out ElevatorDoor door)) - return door; - - return (ElevatorDoor)CreateDoorWrapper(baseElevatorDoor); + base.OnRemove(); + Dictionary.Remove(Base); } } diff --git a/LabApi/Features/Wrappers/Facility/Doors/Gate.cs b/LabApi/Features/Wrappers/Facility/Doors/Gate.cs index da0e144c..553a00d8 100644 --- a/LabApi/Features/Wrappers/Facility/Doors/Gate.cs +++ b/LabApi/Features/Wrappers/Facility/Doors/Gate.cs @@ -5,19 +5,40 @@ namespace LabApi.Features.Wrappers; /// -/// A wrapper representing the +/// A wrapper representing the . /// public class Gate : Door { /// /// Contains all the cached instances, accessible through their . /// - public new static Dictionary Dictionary { get; } = []; + public static new Dictionary Dictionary { get; } = []; /// /// A reference to all instances currently in the game. /// - public new static IReadOnlyCollection List => Dictionary.Values; + public static new IReadOnlyCollection List => Dictionary.Values; + + /// + /// Gets the wrapper from the , or creates a new one if it doesn't exist. + /// + /// The of the door. + /// The requested door wrapper or null if the input was null. + [return: NotNullIfNotNull(nameof(pryableDoor))] + public static Gate? Get(PryableDoor? pryableDoor) + { + if (pryableDoor == null) + { + return null; + } + + if (Dictionary.TryGetValue(pryableDoor, out Gate door)) + { + return door; + } + + return (Gate)CreateDoorWrapper(pryableDoor); + } /// /// An internal constructor to prevent external instantiation. @@ -26,17 +47,12 @@ public class Gate : Door internal Gate(PryableDoor pryableDoor) : base(pryableDoor) { - Dictionary.Add(pryableDoor, this); Base = pryableDoor; - } - /// - /// An internal method to remove itself from the cache when the base object is destroyed. - /// - internal override void OnRemove() - { - base.OnRemove(); - Dictionary.Remove(Base); + if (CanCache) + { + Dictionary.Add(pryableDoor, this); + } } /// @@ -66,19 +82,11 @@ public bool Is106Passable public void Pry() => Base.RpcPryGate(); /// - /// Gets the wrapper from the , or creates a new one if it doesn't exist. + /// An internal method to remove itself from the cache when the base object is destroyed. /// - /// The of the door. - /// The requested door wrapper or null if the input was null. - [return: NotNullIfNotNull(nameof(pryableDoor))] - public static Gate? Get(PryableDoor? pryableDoor) + internal override void OnRemove() { - if (pryableDoor == null) - return null; - - if (Dictionary.TryGetValue(pryableDoor, out Gate door)) - return door; - - return (Gate)CreateDoorWrapper(pryableDoor); + base.OnRemove(); + Dictionary.Remove(Base); } } diff --git a/LabApi/Features/Wrappers/Facility/Doors/NonInteractableDoor.cs b/LabApi/Features/Wrappers/Facility/Doors/NonInteractableDoor.cs index 632e7a03..c18af8e6 100644 --- a/LabApi/Features/Wrappers/Facility/Doors/NonInteractableDoor.cs +++ b/LabApi/Features/Wrappers/Facility/Doors/NonInteractableDoor.cs @@ -12,12 +12,33 @@ public class NonInteractableDoor : Door /// /// Contains all the cached instances, accessible through their . /// - public new static Dictionary Dictionary { get; } = []; + public static new Dictionary Dictionary { get; } = []; /// /// A reference to all instances currently in the game. /// - public new static IReadOnlyCollection List => Dictionary.Values; + public static new IReadOnlyCollection List => Dictionary.Values; + + /// + /// Gets the wrapper from the , or creates a new one if it doesn't exist. + /// + /// The of the door. + /// The requested door wrapper or null if the input was null. + [return: NotNullIfNotNull(nameof(basicNonInteractableDoor))] + public static NonInteractableDoor? Get(BasicNonInteractableDoor? basicNonInteractableDoor) + { + if (basicNonInteractableDoor == null) + { + return null; + } + + if (Dictionary.TryGetValue(basicNonInteractableDoor, out NonInteractableDoor door)) + { + return door; + } + + return (NonInteractableDoor)CreateDoorWrapper(basicNonInteractableDoor); + } /// /// An internal constructor to prevent external instantiation. @@ -26,17 +47,12 @@ public class NonInteractableDoor : Door internal NonInteractableDoor(BasicNonInteractableDoor basicNonInteractableDoor) : base(basicNonInteractableDoor) { - Dictionary.Add(basicNonInteractableDoor, this); Base = basicNonInteractableDoor; - } - /// - /// An internal method to remove itself from the cache when the base object is destroyed. - /// - internal override void OnRemove() - { - base.OnRemove(); - Dictionary.Remove(Base); + if (CanCache) + { + Dictionary.Add(basicNonInteractableDoor, this); + } } /// @@ -54,19 +70,11 @@ public bool Is106Passable } /// - /// Gets the wrapper from the , or creates a new one if it doesn't exist. + /// An internal method to remove itself from the cache when the base object is destroyed. /// - /// The of the door. - /// The requested door wrapper or null if the input was null. - [return: NotNullIfNotNull(nameof(basicNonInteractableDoor))] - public static NonInteractableDoor? Get(BasicNonInteractableDoor? basicNonInteractableDoor) + internal override void OnRemove() { - if (basicNonInteractableDoor == null) - return null; - - if (Dictionary.TryGetValue(basicNonInteractableDoor, out NonInteractableDoor door)) - return door; - - return (NonInteractableDoor)CreateDoorWrapper(basicNonInteractableDoor); + base.OnRemove(); + Dictionary.Remove(Base); } } diff --git a/LabApi/Features/Wrappers/Facility/Doors/Timed173Gate.cs b/LabApi/Features/Wrappers/Facility/Doors/Timed173Gate.cs index 1c9f63ee..69d760d5 100644 --- a/LabApi/Features/Wrappers/Facility/Doors/Timed173Gate.cs +++ b/LabApi/Features/Wrappers/Facility/Doors/Timed173Gate.cs @@ -16,12 +16,33 @@ public class Timed173Gate : Gate /// /// Contains all the cached instances, accessible through their . /// - public new static Dictionary Dictionary { get; } = []; + public static new Dictionary Dictionary { get; } = []; /// /// A reference to all instances currently in the game. /// - public new static IReadOnlyCollection List => Dictionary.Values; + public static new IReadOnlyCollection List => Dictionary.Values; + + /// + /// Gets the wrapper from the , or creates a new one if it doesn't exist. + /// + /// The of the door. + /// The requested door wrapper or null if the input was null. + [return: NotNullIfNotNull(nameof(timed173PryableDoor))] + public static Timed173Gate? Get(Timed173PryableDoor? timed173PryableDoor) + { + if (timed173PryableDoor == null) + { + return null; + } + + if (Dictionary.TryGetValue(timed173PryableDoor, out Timed173Gate door)) + { + return door; + } + + return (Timed173Gate)CreateDoorWrapper(timed173PryableDoor); + } /// /// An internal constructor to prevent external instantiation. @@ -30,17 +51,12 @@ public class Timed173Gate : Gate internal Timed173Gate(Timed173PryableDoor timed173PryableDoor) : base(timed173PryableDoor) { - Dictionary.Add(timed173PryableDoor, this); Base = timed173PryableDoor; - } - /// - /// An internal method to remove itself from the cache when the base object is destroyed. - /// - internal override void OnRemove() - { - base.OnRemove(); - Dictionary.Remove(Base); + if (CanCache) + { + Dictionary.Add(timed173PryableDoor, this); + } } /// @@ -75,19 +91,11 @@ public float Delay } /// - /// Gets the wrapper from the , or creates a new one if it doesn't exist. + /// An internal method to remove itself from the cache when the base object is destroyed. /// - /// The of the door. - /// The requested door wrapper or null if the input was null. - [return: NotNullIfNotNull(nameof(timed173PryableDoor))] - public static Timed173Gate? Get(Timed173PryableDoor? timed173PryableDoor) + internal override void OnRemove() { - if (timed173PryableDoor == null) - return null; - - if (Dictionary.TryGetValue(timed173PryableDoor, out Timed173Gate door)) - return door; - - return (Timed173Gate)CreateDoorWrapper(timed173PryableDoor); + base.OnRemove(); + Dictionary.Remove(Base); } } diff --git a/LabApi/Features/Wrappers/Facility/Elevator.cs b/LabApi/Features/Wrappers/Facility/Elevator.cs index eadc26d4..7a329a66 100644 --- a/LabApi/Features/Wrappers/Facility/Elevator.cs +++ b/LabApi/Features/Wrappers/Facility/Elevator.cs @@ -1,10 +1,13 @@ -using Interactables.Interobjects; +using System; +using Generators; +using Interactables.Interobjects; using Interactables.Interobjects.DoorUtils; using MapGeneration.Distributors; using System.Collections.Generic; using System.Linq; using UnityEngine; -using Generators; +using Utils; +using BaseElevatorDoor = Interactables.Interobjects.ElevatorDoor; namespace LabApi.Features.Wrappers; @@ -24,19 +27,41 @@ public class Elevator public static IReadOnlyCollection List => Dictionary.Values; /// - /// A private constructor to prevent external instantiation. + /// Locks every door of every elevator on map. /// - /// The of the elevator. - private Elevator(ElevatorChamber elevator) + public static void LockAll() { - Dictionary.Add(elevator, this); - Base = elevator; + foreach (Elevator el in List) + { + el.LockAllDoors(); + } } /// - /// The base object. + /// Unlocks every door of every elevator on map. /// - public ElevatorChamber Base { get; } + public static void UnlockAll() + { + foreach (Elevator el in List) + { + el.UnlockAllDoors(); + } + } + + /// + /// Gets the elevator wrapper from the , or creates a new one if it doesn't exist. + /// + /// The of the elevator. + /// The requested elevator. + public static Elevator Get(ElevatorChamber elevatorChamber) => + Dictionary.TryGetValue(elevatorChamber, out Elevator generator) ? generator : new Elevator(elevatorChamber); + + /// + /// Gets the enumerable of elevators that are assigned to the specific group. + /// + /// The specified elevator group. + /// Enumerable where the group is equal to the one specified. + public static IEnumerable GetByGroup(ElevatorGroup group) => List.Where(n => n.Group == group); /// /// Initializes the class to subscribe to events. @@ -50,6 +75,31 @@ internal static void Initialize() ElevatorChamber.OnElevatorRemoved += (chamber) => Dictionary.Remove(chamber); } + /// + /// A private constructor to prevent external instantiation. + /// + /// The of the elevator. + private Elevator(ElevatorChamber elevator) + { + Dictionary.Add(elevator, this); + Base = elevator; + } + + /// + /// The base object. + /// + public ElevatorChamber Base { get; } + + /// + /// Gets all the doors associated with this elevator. + /// + public IEnumerable Doors => BaseElevatorDoor.GetDoorsForGroup(Group).Select(ElevatorDoor.Get)!; + + /// + /// Gets all the rooms associated with this elevator. + /// + public IEnumerable Rooms => Doors.SelectMany(static x => x.Rooms); + /// /// Gets the current destination / location of the elevator. /// @@ -98,7 +148,15 @@ public ElevatorGroup Group /// Gets the current world space bounds of this elevator. /// World space bounds are cached and recalculated if not valid after elevator movement. /// - public Bounds WorldSpaceBounds => Base.WorldspaceBounds; + // Rename WorldSpaceRelativeBounds to WorldSpaceBounds in the next major. + [Obsolete("Use WorldSpaceRelativeBounds.Bounds instead.")] + public Bounds WorldSpaceBounds => Base.WorldspaceBounds.Bounds; + + /// + /// Gets the current world space bounds of this elevator. + /// World space bounds are cached and recalculated if not valid after elevator movement. + /// + public RelativeBounds WorldSpaceRelativeBounds => Base.WorldspaceBounds; /// /// Gets the reason why is ANY elevator door locked. @@ -126,24 +184,6 @@ public override string ToString() return $"[Elevator: Group={Group}, IsReady={IsReady}, GoingUp={GoingUp}, CurrentSequence={CurrentSequence}]"; } - /// - /// Locks every door of every elevator on map. - /// - public static void LockAll() - { - foreach (Elevator el in List) - el.LockAllDoors(); - } - - /// - /// Unlocks every door of every elevator on map. - /// - public static void UnlockAll() - { - foreach (Elevator el in List) - el.UnlockAllDoors(); - } - /// /// Attempts to send the elevator to target destination. /// @@ -171,19 +211,4 @@ public static void UnlockAll() /// Unlocks all elevator doors assigned to this chamber. /// public void UnlockAllDoors() => Base.ServerLockAllDoors(DoorLockReason.AdminCommand, false); - - /// - /// Gets the elevator wrapper from the , or creates a new one if it doesn't exist. - /// - /// The of the elevator. - /// The requested elevator. - public static Elevator Get(ElevatorChamber elevatorChamber) => - Dictionary.TryGetValue(elevatorChamber, out Elevator generator) ? generator : new Elevator(elevatorChamber); - - /// - /// Gets the enumerable of elevators that are assigned to the specific group. - /// - /// The specified elevator group. - /// Enumerable where the group is equal to the one specified. - public static IEnumerable GetByGroup(ElevatorGroup group) => List.Where(n => n.Group == group); } \ No newline at end of file diff --git a/LabApi/Features/Wrappers/Facility/Hazards/AmnesticCloudHazard.cs b/LabApi/Features/Wrappers/Facility/Hazards/AmnesticCloudHazard.cs index 85686f90..b533b027 100644 --- a/LabApi/Features/Wrappers/Facility/Hazards/AmnesticCloudHazard.cs +++ b/LabApi/Features/Wrappers/Facility/Hazards/AmnesticCloudHazard.cs @@ -14,17 +14,83 @@ public class AmnesticCloudHazard : DecayableHazard /// /// Contains all the cached items, accessible through their . /// - public new static Dictionary Dictionary { get; } = []; + public static new Dictionary Dictionary { get; } = []; /// /// Gets all currently active tantrum hazards. /// - public new IReadOnlyCollection List => Dictionary.Values; + public static new IReadOnlyCollection List => Dictionary.Values; /// /// Prefab used to spawn the hazard. /// - protected static new Scp939AmnesticCloudInstance? BasePrefab; + protected static new Scp939AmnesticCloudInstance? BasePrefab { get; private set; } + + /// + /// Spawns a at specified position with specified rotation, scale duration and size. + /// Do note that changing scale doesn't change the effect size. Use the and to match the visual size. + /// + /// The target position to spawn this hazard at. + /// The target rotation to spawn this hazard with. + /// The target scale to spawn with. + /// The duration in seconds for which this cloud will be alive for. + /// The size of the cloud. + /// The owner of the cloud. + /// A new hazard. + public static AmnesticCloudHazard Spawn(Vector3 position, Quaternion rotation, Vector3 scale, float duration = 90f, byte size = 255, Player? owner = null) + { + if (BasePrefab == null) + { + BasePrefab = GetPrefab(); + } + + AmnesticCloudHazard hazard = (AmnesticCloudHazard)Hazard.Spawn(BasePrefab!, position, rotation, scale); + hazard.Base.State = CloudState.Created; + hazard.LiveDuration = duration; + hazard.VisualSize = size; + hazard.SyncedPosition = position; + + Vector2 minMax = hazard.Base.MinMaxTime; + hazard.MaxDistance = Mathf.Lerp(minMax.x, minMax.y, size / byte.MaxValue); + + if (owner != null) + { + hazard.Owner = owner; + } + + return hazard; + } + + /// + /// Gets the hazard wrapper from the or creates a new one if it doesn't exist and the provided was not . + /// + /// The of the hazard. + /// The requested hazard or . + [return: NotNullIfNotNull(nameof(hazard))] + public static AmnesticCloudHazard? Get(Scp939AmnesticCloudInstance? hazard) + { + if (hazard == null) + { + return null; + } + + return Dictionary.TryGetValue(hazard, out AmnesticCloudHazard decHazard) ? decHazard : (AmnesticCloudHazard)CreateItemWrapper(hazard)!; + } + + /// + /// Internal constructor preventing external instantiation. + /// + /// The base amnestic cloud hazard. + internal AmnesticCloudHazard(Scp939AmnesticCloudInstance hazard) + : base(hazard) + { + Base = hazard; + + if (CanCache) + { + Dictionary.Add(hazard, this); + } + } /// /// Gets or sets the world position of the hazard as it is synchronized with the client. @@ -92,51 +158,10 @@ public Player? Owner /// public new Scp939AmnesticCloudInstance Base { get; } - /// - /// Internal constructor preventing external instantiation. - /// - /// The base amnestic cloud hazard. - internal AmnesticCloudHazard(Scp939AmnesticCloudInstance hazard) - : base(hazard) - { - Base = hazard; - Dictionary.Add(hazard, this); - } - - /// - /// Spawns a at specified position with specified rotation, scale duration and size. - /// Do note that changing scale doesn't change the effect size. Use the and to match the visual size. - /// - /// The target position to spawn this hazard at. - /// The target rotation to spawn this hazard with. - /// The target scale to spawn with. - /// The duration in seconds for which this cloud will be alive for. - /// The size of the cloud. - /// The owner of the cloud. - /// A new hazard. - public static AmnesticCloudHazard Spawn(Vector3 position, Quaternion rotation, Vector3 scale, float duration = 90f, byte size = 255, Player? owner = null) - { - if (BasePrefab == null) - BasePrefab = GetPrefab(); - - AmnesticCloudHazard hazard = (AmnesticCloudHazard)Hazard.Spawn(BasePrefab, position, rotation, scale); - hazard.Base.State = CloudState.Created; - hazard.LiveDuration = duration; - hazard.VisualSize = size; - hazard.SyncedPosition = position; - - Vector2 minMax = hazard.Base.MinMaxTime; - hazard.MaxDistance = Mathf.Lerp(minMax.x, minMax.y, size / byte.MaxValue); - - if (owner != null) - hazard.Owner = owner; - return hazard; - } - /// /// Temporary pauses all amnesia effects based on or custom time. /// - /// Custom duration of the pause. Values less than 0 will use the + /// Custom duration of the pause. Values less than 0 will use the . public void Pause(float customDuration = -1f) { if (customDuration > 0f) @@ -160,18 +185,4 @@ internal override void OnRemove() base.OnRemove(); Dictionary.Remove(Base); } - - /// - /// Gets the hazard wrapper from the or creates a new one if it doesn't exist and the provided was not . - /// - /// The of the hazard. - /// The requested hazard or . - [return: NotNullIfNotNull(nameof(hazard))] - public static AmnesticCloudHazard? Get(Scp939AmnesticCloudInstance? hazard) - { - if (hazard == null) - return null; - - return Dictionary.TryGetValue(hazard, out AmnesticCloudHazard decHazard) ? decHazard : (AmnesticCloudHazard)CreateItemWrapper(hazard); - } } \ No newline at end of file diff --git a/LabApi/Features/Wrappers/Facility/Hazards/DecayableHazard.cs b/LabApi/Features/Wrappers/Facility/Hazards/DecayableHazard.cs index 9f16f9a1..2f96f670 100644 --- a/LabApi/Features/Wrappers/Facility/Hazards/DecayableHazard.cs +++ b/LabApi/Features/Wrappers/Facility/Hazards/DecayableHazard.cs @@ -13,12 +13,43 @@ public class DecayableHazard : Hazard /// /// Contains all the cached items, accessible through their . /// - public new static Dictionary Dictionary { get; } = []; + public static new Dictionary Dictionary { get; } = []; /// /// Gets all currently active decayable hazards. /// - public new IReadOnlyCollection List => Dictionary.Values; + public static new IReadOnlyCollection List => Dictionary.Values; + + /// + /// Gets the hazard wrapper from the or creates a new one if it doesn't exist and the provided was not . + /// + /// The of the hazard. + /// The requested hazard or . + [return: NotNullIfNotNull(nameof(hazard))] + public static DecayableHazard? Get(TemporaryHazard? hazard) + { + if (hazard == null) + { + return null; + } + + return Dictionary.TryGetValue(hazard, out DecayableHazard decHazard) ? decHazard : (DecayableHazard)CreateItemWrapper(hazard)!; + } + + /// + /// An internal constructor to prevent external instantiation. + /// + /// The base game object. + protected DecayableHazard(TemporaryHazard hazard) + : base(hazard) + { + Base = hazard; + + if (CanCache) + { + Dictionary.Add(hazard, this); + } + } /// /// Gets or sets the modifier applied to when calculating how much time has passed.
@@ -54,20 +85,9 @@ public float Elapsed ///
public new TemporaryHazard Base { get; } - /// - /// An internal constructor to prevent external instantiation. - /// - /// The base game object. - protected DecayableHazard(TemporaryHazard hazard) - : base(hazard) - { - Base = hazard; - Dictionary.Add(hazard, this); - } - /// /// Destroys this hazard.
- /// Do note that subclasses usually implement few seconds delay before the actual object is destroyed. (Usually to wait for animations to finish on clients) + /// Do note that subclasses usually implement few seconds delay before the actual object is destroyed (Usually to wait for animations to finish on clients). ///
public override void Destroy() => Base.ServerDestroy(); @@ -77,18 +97,4 @@ internal override void OnRemove() base.OnRemove(); Dictionary.Remove(Base); } - - /// - /// Gets the hazard wrapper from the or creates a new one if it doesn't exist and the provided was not . - /// - /// The of the hazard. - /// The requested hazard or . - [return: NotNullIfNotNull(nameof(hazard))] - public static DecayableHazard? Get(TemporaryHazard? hazard) - { - if (hazard == null) - return null; - - return Dictionary.TryGetValue(hazard, out DecayableHazard decHazard) ? decHazard : (DecayableHazard)CreateItemWrapper(hazard); - } } \ No newline at end of file diff --git a/LabApi/Features/Wrappers/Facility/Hazards/Hazard.cs b/LabApi/Features/Wrappers/Facility/Hazards/Hazard.cs index 70a2ff5a..6b90eaa4 100644 --- a/LabApi/Features/Wrappers/Facility/Hazards/Hazard.cs +++ b/LabApi/Features/Wrappers/Facility/Hazards/Hazard.cs @@ -1,13 +1,13 @@ -using Hazards; +using Generators; +using Hazards; using InventorySystem; +using Mirror; +using PlayerRoles.PlayableScps.Scp939; using System; using System.Collections.Generic; +using System.Diagnostics.CodeAnalysis; using System.Linq; -using Generators; using UnityEngine; -using Mirror; -using System.Diagnostics.CodeAnalysis; -using PlayerRoles.PlayableScps.Scp939; using Logger = LabApi.Features.Console.Logger; namespace LabApi.Features.Wrappers; @@ -20,7 +20,7 @@ public class Hazard /// /// Contains all the handlers for constructing wrappers for the associated base game types. /// - private static readonly Dictionary> typeWrappers = []; + private static readonly Dictionary> TypeWrappers = []; /// /// Contains all the cached items, accessible through their . @@ -35,81 +35,72 @@ public class Hazard /// /// Prefab used to spawn the hazard. /// - protected static EnvironmentalHazard? BasePrefab; + protected static EnvironmentalHazard? BasePrefab { get; private set; } /// - /// Base game object. - /// - public EnvironmentalHazard Base { get; private set; } - - /// - /// Gets all affected players by this hazard. - /// - public IEnumerable AffectedPlayers => Base.AffectedPlayers.Select(n => Player.Get(n)); - - /// - /// Gets or sets the maximum distance players have to be at, for this hazard to affect them. + /// Spawns a at specified position with specified rotation and scale. /// - public float MaxDistance + /// The target prefab. + /// The target position to spawn this hazard at. + /// The target rotation to spawn this hazard with. + /// The target scale to spawn with. + /// A new hazard. + public static Hazard Spawn(EnvironmentalHazard prefab, Vector3 position, Quaternion rotation, Vector3 scale) { - get => Base.MaxDistance; - set => Base.MaxDistance = value; - } + EnvironmentalHazard hazard = GameObject.Instantiate(prefab); + hazard.transform.SetPositionAndRotation(position, rotation); + hazard.transform.localScale = scale; - /// - /// Gets or sets the maximum height players have to be at, for this hazard to affect them. - /// - public float MaxHeightDistance - { - get => Base.MaxHeightDistance; - set => Base.MaxHeightDistance = value; + return Get(hazard); } /// - /// Gets or sets the offset applied to the . + /// Gets the hazard wrapper from the or creates a new one if it doesn't exist and the provided was not . /// - public virtual Vector3 SourceOffset + /// The of the hazard. + /// The requested hazard or . + [return: NotNullIfNotNull(nameof(hazard))] + public static Hazard? Get(EnvironmentalHazard? hazard) { - get => Base.SourceOffset; - set => Base.SourceOffset = value; - } + if (hazard == null) + { + return null; + } - /// - /// Gets whether this environmental hazard and it's effects is enabled. - /// Setting to false also stops the decay of temporary hazards. - /// - public virtual bool IsActive - { - get => Base.IsActive; - set => Base.IsActive = value; + return Dictionary.TryGetValue(hazard, out Hazard wrapper) ? wrapper : CreateItemWrapper(hazard)!; } /// - /// Gets or sets the origin point from which the AoE effect will start. + /// Tries to get the hazard wrapper from the . /// - public virtual Vector3 SourcePosition + /// The of the hazard. + /// The requested hazard. + /// if the item exists, otherwise . + public static bool TryGet(EnvironmentalHazard? envHazard, [NotNullWhen(true)] out Hazard? wrapper) { - get => Base.SourcePosition; - set => Base.SourcePosition = value; + wrapper = Get(envHazard); + return wrapper != null; } /// - /// Gets whether the hazard is destroyed. - /// - public bool IsDestroyed => Base == null || Base.gameObject == null; - - /// - /// Gets the room in which this hazard is in. - /// - public Room? Room => Room.GetRoomAtPosition(SourcePosition); - - /// - /// Initializes the class to subscribe to events and handle the item caching. + /// Gets all hazards in a specified room. /// - protected Hazard(EnvironmentalHazard hazard) + /// The target room to check on. + /// Hazards in specified room. + public static IEnumerable Get(Room? room) { - Base = hazard; - Dictionary.Add(hazard, this); + if (room == null) + { + yield break; + } + + foreach (Hazard hazard in List) + { + if (hazard.Room == room) + { + yield return hazard; + } + } } /// @@ -129,46 +120,38 @@ internal static void Initialize() } /// - /// An internal virtual method to signal to derived implementations to uncache when the base object is destroyed. - /// - internal virtual void OnRemove() - { - } - - /// - public override string ToString() - { - return $"[{GetType().Name}: MaxDistance={MaxDistance}, MaxHeightDistance={MaxHeightDistance}, SourcePosition={SourcePosition}, SourceOffset={SourceOffset}, IsActive={IsActive}, IsDestroyed={IsDestroyed}]"; - } - - /// - /// Spawns a at specified position with specified rotation and scale. + /// Creates a new wrapper from the base environmental hazard object. /// - /// The target prefab. - /// The target position to spawn this hazard at. - /// The target rotation to spawn this hazard with. - /// The target scale to spawn with. - /// A new hazard. - public static Hazard Spawn(EnvironmentalHazard prefab, Vector3 position, Quaternion rotation, Vector3 scale) + /// The base object. + /// The newly created wrapper. + protected static Hazard? CreateItemWrapper(EnvironmentalHazard hazard) { - EnvironmentalHazard hazard = GameObject.Instantiate(prefab); - hazard.transform.SetPositionAndRotation(position, rotation); - hazard.transform.localScale = scale; + Type targetType = hazard.GetType(); + if (!TypeWrappers.TryGetValue(targetType, out Func ctorFunc)) + { +#if DEBUG + Logger.Warn($"Unable to find {nameof(Hazard)} wrapper for {targetType.Name}, backup up to base constructor!"); +#endif + return new Hazard(hazard); + } - return Get(hazard); + return ctorFunc.Invoke(hazard); } /// /// Attempts to get the prefab from . /// /// Type of the hazard. - /// Prefab if it was found. Otherwise - protected static T? GetPrefab() where T : EnvironmentalHazard + /// Prefab if it was found. Otherwise . + protected static T? GetPrefab() + where T : EnvironmentalHazard { foreach (GameObject prefab in NetworkClient.prefabs.Values) { if (!prefab.TryGetComponent(out T hazard)) + { continue; + } return hazard; } @@ -176,22 +159,6 @@ public static Hazard Spawn(EnvironmentalHazard prefab, Vector3 position, Quatern return null; } - /// - /// Gets whether the player is in the hazard area. - /// - /// Target player to check on. - /// Whether the player is within hazard area. - public bool IsInArea(Player player) => Base.IsInArea(SourcePosition, player.Position); - - /// - /// Destroys this hazard. - /// - public virtual void Destroy() - { - if (Base.gameObject != null) - NetworkServer.Destroy(Base.gameObject); - } - /// /// A private method to handle the creation of new hazards in the server. /// @@ -199,7 +166,9 @@ public virtual void Destroy() private static void AddHazard(EnvironmentalHazard hazard) { if (!Dictionary.ContainsKey(hazard)) + { _ = CreateItemWrapper(hazard); + } } /// @@ -219,71 +188,125 @@ private static void RemoveHazard(EnvironmentalHazard hazard) /// /// The derived base game type to handle. /// A handler to construct the wrapper with the base game instance. - private static void Register(Func constructor) where T : EnvironmentalHazard + private static void Register(Func constructor) + where T : EnvironmentalHazard { - typeWrappers.Add(typeof(T), x => constructor((T)x)); + TypeWrappers.Add(typeof(T), x => constructor((T)x)); } /// - /// Creates a new wrapper from the base envronental hazard object. + /// Initializes the class to subscribe to events and handle the item caching. /// - /// The base object. - /// The newly created wrapper. - protected static Hazard? CreateItemWrapper(EnvironmentalHazard hazard) + /// The base game hazard component. + protected Hazard(EnvironmentalHazard hazard) { - Type targetType = hazard.GetType(); - if (!typeWrappers.TryGetValue(targetType, out Func ctorFunc)) + Base = hazard; + + if (CanCache) { -#if DEBUG - Logger.Warn($"Unable to find {nameof(Hazard)} wrapper for {targetType.Name}, backup up to base constructor!"); -#endif - return new Hazard(hazard); + Dictionary.Add(hazard, this); } + } - return ctorFunc.Invoke(hazard); + /// + /// Base game object. + /// + public EnvironmentalHazard Base { get; private set; } + + /// + /// Gets all affected players by this hazard. + /// + public IEnumerable AffectedPlayers => Base.AffectedPlayers.Select(n => Player.Get(n)); + + /// + /// Gets or sets the maximum distance players have to be at, for this hazard to affect them. + /// + public float MaxDistance + { + get => Base.MaxDistance; + set => Base.MaxDistance = value; } /// - /// Gets the hazard wrapper from the or creates a new one if it doesn't exist and the provided was not . + /// Gets or sets the maximum height players have to be at, for this hazard to affect them. /// - /// The of the hazard. - /// The requested hazard or . - [return: NotNullIfNotNull(nameof(hazard))] - public static Hazard? Get(EnvironmentalHazard? hazard) + public float MaxHeightDistance { - if (hazard == null) - return null; + get => Base.MaxHeightDistance; + set => Base.MaxHeightDistance = value; + } - return Dictionary.TryGetValue(hazard, out Hazard wrapper) ? wrapper : CreateItemWrapper(hazard); + /// + /// Gets or sets the offset applied to the . + /// + public virtual Vector3 SourceOffset + { + get => Base.SourceOffset; + set => Base.SourceOffset = value; } + /// + /// Gets whether this environmental hazard and it's effects is enabled. + /// Setting to false also stops the decay of temporary hazards. + /// + public virtual bool IsActive + { + get => Base.IsActive; + set => Base.IsActive = value; + } /// - /// Tries to get the hazard wrapper from the . + /// Gets or sets the origin point from which the AoE effect will start. /// - /// The of the hazard. - /// The requested hazard. - /// if the item exists, otherwise . - public static bool TryGet(EnvironmentalHazard? envHazard, [NotNullWhen(true)] out Hazard? wrapper) + public virtual Vector3 SourcePosition { - wrapper = Get(envHazard); - return wrapper != null; + get => Base.SourcePosition; + set => Base.SourcePosition = value; } /// - /// Gets all hazards in a specified room. + /// Gets whether the hazard is destroyed. /// - /// The target room to check on. - /// Hazards in specified room. - public static IEnumerable Get(Room? room) + public bool IsDestroyed => Base == null || Base.gameObject == null; + + /// + /// Gets the room in which this hazard is in. + /// + public Room? Room => Room.GetRoomAtPosition(SourcePosition); + + /// + /// Whether to cache the wrapper. + /// + protected bool CanCache => !IsDestroyed && Base.isActiveAndEnabled; + + /// + public override string ToString() { - if (room == null) - yield break; + return $"[{GetType().Name}: MaxDistance={MaxDistance}, MaxHeightDistance={MaxHeightDistance}, SourcePosition={SourcePosition}, SourceOffset={SourceOffset}, IsActive={IsActive}, IsDestroyed={IsDestroyed}]"; + } - foreach (Hazard hazard in List) + /// + /// Gets whether the player is in the hazard area. + /// + /// Target player to check on. + /// Whether the player is within hazard area. + public bool IsInArea(Player player) => Base.IsInArea(SourcePosition, player.Position); + + /// + /// Destroys this hazard. + /// + public virtual void Destroy() + { + if (Base.gameObject != null) { - if (hazard.Room == room) - yield return hazard; + NetworkServer.Destroy(Base.gameObject); } } + + /// + /// An internal virtual method to signal to derived implementations to uncache when the base object is destroyed. + /// + internal virtual void OnRemove() + { + } } \ No newline at end of file diff --git a/LabApi/Features/Wrappers/Facility/Hazards/SinkholeHazard.cs b/LabApi/Features/Wrappers/Facility/Hazards/SinkholeHazard.cs index 3264a331..9cd1eb3f 100644 --- a/LabApi/Features/Wrappers/Facility/Hazards/SinkholeHazard.cs +++ b/LabApi/Features/Wrappers/Facility/Hazards/SinkholeHazard.cs @@ -1,8 +1,8 @@ using Hazards; -using System.Collections.Generic; -using UnityEngine; using Mirror; +using System.Collections.Generic; using System.Diagnostics.CodeAnalysis; +using UnityEngine; namespace LabApi.Features.Wrappers; @@ -15,42 +15,17 @@ public class SinkholeHazard : Hazard /// /// Contains all the cached items, accessible through their . /// - public new static Dictionary Dictionary { get; } = []; + public static new Dictionary Dictionary { get; } = []; /// /// Gets all currently active sinkholes. /// - public new IReadOnlyCollection List => Dictionary.Values; + public static new IReadOnlyCollection List => Dictionary.Values; /// /// Prefab used to spawn the hazard. /// - protected static new SinkholeEnvironmentalHazard? BasePrefab; - - /// - /// The base object. - /// - public new SinkholeEnvironmentalHazard Base { get; } - - /// - /// An internal constructor to prevent external instantiation. - /// - /// The base object. - internal SinkholeHazard(SinkholeEnvironmentalHazard hazard) - : base(hazard) - { - Base = hazard; - Dictionary.Add(hazard, this); - } - - /// - /// An internal method to remove itself from the cache when the base object is destroyed. - /// - internal override void OnRemove() - { - base.OnRemove(); - Dictionary.Remove(Base); - } + protected static new SinkholeEnvironmentalHazard? BasePrefab { get; private set; } /// /// Spawns a at specified position with specified rotation and scale. @@ -63,9 +38,11 @@ internal override void OnRemove() public static SinkholeHazard Spawn(Vector3 position, Quaternion rotation, Vector3 scale) { if (BasePrefab == null) + { BasePrefab = GetPrefab(); + } - SinkholeHazard hazard = (SinkholeHazard)Hazard.Spawn(BasePrefab, position, rotation, scale); + SinkholeHazard hazard = (SinkholeHazard)Hazard.Spawn(BasePrefab!, position, rotation, scale); hazard.IsActive = true; return hazard; } @@ -79,8 +56,39 @@ public static SinkholeHazard Spawn(Vector3 position, Quaternion rotation, Vector public static SinkholeHazard? Get(SinkholeEnvironmentalHazard? hazard) { if (hazard == null) + { return null; + } + + return Dictionary.TryGetValue(hazard, out SinkholeHazard sinkhole) ? sinkhole : (SinkholeHazard)CreateItemWrapper(hazard)!; + } + + /// + /// An internal constructor to prevent external instantiation. + /// + /// The base object. + internal SinkholeHazard(SinkholeEnvironmentalHazard hazard) + : base(hazard) + { + Base = hazard; + + if (CanCache) + { + Dictionary.Add(hazard, this); + } + } - return Dictionary.TryGetValue(hazard, out SinkholeHazard sinkhole) ? sinkhole : (SinkholeHazard)CreateItemWrapper(hazard); + /// + /// The base object. + /// + public new SinkholeEnvironmentalHazard Base { get; } + + /// + /// An internal method to remove itself from the cache when the base object is destroyed. + /// + internal override void OnRemove() + { + base.OnRemove(); + Dictionary.Remove(Base); } } \ No newline at end of file diff --git a/LabApi/Features/Wrappers/Facility/Hazards/TantrumHazard.cs b/LabApi/Features/Wrappers/Facility/Hazards/TantrumHazard.cs index f0973f27..e87ba27b 100644 --- a/LabApi/Features/Wrappers/Facility/Hazards/TantrumHazard.cs +++ b/LabApi/Features/Wrappers/Facility/Hazards/TantrumHazard.cs @@ -13,44 +13,53 @@ public class TantrumHazard : DecayableHazard /// /// Contains all the cached items, accessible through their . /// - public new static Dictionary Dictionary { get; } = []; + public static new Dictionary Dictionary { get; } = []; /// /// Gets all currently active tantrum hazards. /// - public new IReadOnlyCollection List => Dictionary.Values; + public static new IReadOnlyCollection List => Dictionary.Values; /// /// Prefab used to spawn the hazard. /// - protected static new TantrumEnvironmentalHazard? BasePrefab; + protected static new TantrumEnvironmentalHazard? BasePrefab { get; private set; } /// - /// Gets or sets the world position of the hazard as it is synchronized with the client. - /// Note that this value is slightly inaccurate and is purely for visual effects.
- /// For actual world position used to calculate whether the player is inside of this hazard use . + /// Spawns a at specified position with specified rotation and scale. + /// Do note that changing scale doesn't change the effect size. Use the and to match the visual size. ///
- public Vector3 SyncedPosition + /// The target position to spawn this hazard at. + /// The target rotation to spawn this hazard with. + /// The target scale to spawn with. + /// A new tantrum hazard. + public static TantrumHazard Spawn(Vector3 position, Quaternion rotation, Vector3 scale) { - get => Base.SynchronizedPosition.Position; - set => Base.SynchronizedPosition = new RelativePositioning.RelativePosition(value); + if (BasePrefab == null) + { + BasePrefab = Hazard.GetPrefab(); + } + + TantrumHazard hazard = (TantrumHazard)Hazard.Spawn(BasePrefab!, position, rotation, scale); + hazard.SyncedPosition = position; + return hazard; } /// - /// Gets or sets whether a slight sizzle sound effect will be played when this object is destroyed. - /// It is played by default if the tantrum gets destroyed by an explosion or by .
- /// Note that this state may change right before it is destroyed by standard game means. + /// Gets the hazard wrapper from the or creates a new one if it doesn't exist and the provided was not . ///
- public bool PlaySizzle + /// The of the hazard. + /// The requested hazard or . + [return: NotNullIfNotNull(nameof(hazard))] + public static TantrumHazard? Get(TantrumEnvironmentalHazard? hazard) { - get => Base.PlaySizzle; - set => Base.PlaySizzle = value; - } + if (hazard == null) + { + return null; + } - /// - /// The base object. - /// - public new TantrumEnvironmentalHazard Base { get; } + return Dictionary.TryGetValue(hazard, out TantrumHazard decHazard) ? decHazard : (TantrumHazard)CreateItemWrapper(hazard)!; + } /// /// An internal constructor to prevent external instantiation. @@ -61,47 +70,45 @@ internal TantrumHazard(TantrumEnvironmentalHazard hazard) { Base = hazard; - Dictionary.Add(hazard, this); + if (CanCache) + { + Dictionary.Add(hazard, this); + } } /// - /// Spawns a at specified position with specified rotation and scale. - /// Do note that changing scale doesn't change the effect size. Use the and to match the visual size. + /// Gets or sets the world position of the hazard as it is synchronized with the client. + /// Note that this value is slightly inaccurate and is purely for visual effects.
+ /// For actual world position used to calculate whether the player is inside of this hazard use . ///
- /// The target position to spawn this hazard at. - /// The target rotation to spawn this hazard with. - /// The target scale to spawn with. - /// A new tantrum hazard. - public static TantrumHazard Spawn(Vector3 position, Quaternion rotation, Vector3 scale) + public Vector3 SyncedPosition { - if (BasePrefab == null) - BasePrefab = Hazard.GetPrefab(); - - TantrumHazard hazard = (TantrumHazard)Hazard.Spawn(BasePrefab, position, rotation, scale); - hazard.SyncedPosition = position; - return hazard; + get => Base.SynchronizedPosition.Position; + set => Base.SynchronizedPosition = new RelativePositioning.RelativePosition(value); } /// - /// An internal method to remove itself from the cache when the base object is destroyed. + /// Gets or sets whether a slight sizzle sound effect will be played when this object is destroyed. + /// It is played by default if the tantrum gets destroyed by an explosion or by .
+ /// Note that this state may change right before it is destroyed by standard game means. ///
- internal override void OnRemove() + public bool PlaySizzle { - base.OnRemove(); - Dictionary.Remove(Base); + get => Base.PlaySizzle; + set => Base.PlaySizzle = value; } /// - /// Gets the hazard wrapper from the or creates a new one if it doesn't exist and the provided was not . + /// The base object. /// - /// The of the hazard. - /// The requested hazard or - [return: NotNullIfNotNull(nameof(hazard))] - public static TantrumHazard? Get(TantrumEnvironmentalHazard? hazard) - { - if (hazard == null) - return null; + public new TantrumEnvironmentalHazard Base { get; } - return Dictionary.TryGetValue(hazard, out TantrumHazard decHazard) ? decHazard : (TantrumHazard)CreateItemWrapper(hazard); + /// + /// An internal method to remove itself from the cache when the base object is destroyed. + /// + internal override void OnRemove() + { + base.OnRemove(); + Dictionary.Remove(Base); } } \ No newline at end of file diff --git a/LabApi/Features/Wrappers/Facility/Hazards/Tesla.cs b/LabApi/Features/Wrappers/Facility/Hazards/Tesla.cs index 42908351..ec0eeb1d 100644 --- a/LabApi/Features/Wrappers/Facility/Hazards/Tesla.cs +++ b/LabApi/Features/Wrappers/Facility/Hazards/Tesla.cs @@ -1,9 +1,9 @@ -using System.Collections.Generic; +using Generators; +using MapGeneration; +using System.Collections.Generic; using System.Diagnostics.CodeAnalysis; using UnityEngine; using Utils.NonAllocLINQ; -using Generators; -using MapGeneration; namespace LabApi.Features.Wrappers; @@ -17,15 +17,58 @@ public class Tesla ///
public static Dictionary Dictionary { get; } = []; + /// + /// A reference to all instances of . + /// + public static IReadOnlyCollection List => Dictionary.Values; + /// /// Cached tesla gates by they are in. /// private static Dictionary TeslaByRoom { get; } = []; /// - /// A reference to all instances of . + /// Gets the tesla wrapper from the or creates a new one if it doesn't exist. /// - public static IReadOnlyCollection List => Dictionary.Values; + /// The of the tesla. + /// The requested tesla. + public static Tesla Get(TeslaGate teslaGate) => Dictionary.TryGetValue(teslaGate, out Tesla tesla) ? tesla : new Tesla(teslaGate); + + /// + /// Gets the tesla wrapper inside of from the . + /// + /// The with the tesla. + /// The tesla to be returned. + /// Whether the tesla is in out parameter. + public static bool TryGet(Room room, [NotNullWhen(true)] out Tesla? tesla) + => TeslaByRoom.TryGetValue(room.Base, out tesla); + + /// + /// Initializes the class to subscribe to events and handle the tesla caching. + /// + [InitializeWrapper] + internal static void Initialize() + { + Dictionary.Clear(); + TeslaByRoom.Clear(); + TeslaGate.OnAdded += (tesla) => _ = new Tesla(tesla); + TeslaGate.OnRemoved += (tesla) => + { + Dictionary.Remove(tesla); + TeslaByRoom.Remove(tesla.Room); + }; + } + + /// + /// A private constructor to prevent external instantiation. + /// + /// The of the item. + private Tesla(TeslaGate tesla) + { + Dictionary.Add(tesla, this); + TeslaByRoom.Add(tesla.Room, this); + Base = tesla; + } /// /// The base of the tesla. @@ -103,47 +146,4 @@ public float InactiveTime /// Tesla gate instant burst. /// public void InstantTrigger() => Base.RpcInstantBurst(); - - /// - /// Initializes the class to subscribe to events and handle the tesla caching. - /// - [InitializeWrapper] - internal static void Initialize() - { - Dictionary.Clear(); - TeslaByRoom.Clear(); - TeslaGate.OnAdded += (tesla) => _ = new Tesla(tesla); - TeslaGate.OnRemoved += (tesla) => - { - Dictionary.Remove(tesla); - TeslaByRoom.Remove(tesla.Room); - }; - } - - /// - /// A private constructor to prevent external instantiation. - /// - /// The of the item. - private Tesla(TeslaGate tesla) - { - Dictionary.Add(tesla, this); - TeslaByRoom.Add(tesla.Room, this); - Base = tesla; - } - - /// - /// Gets the tesla wrapper from the or creates a new one if it doesn't exist. - /// - /// The of the tesla. - /// The requested tesla. - public static Tesla Get(TeslaGate teslaGate) => Dictionary.TryGetValue(teslaGate, out Tesla tesla) ? tesla : new Tesla(teslaGate); - - /// - /// Gets the tesla wrapper inside of from the . - /// - /// The with the tesla. - /// The tesla to be returned. - /// Whether the tesla is in out parameter. - public static bool TryGet(Room room, [NotNullWhen(true)] out Tesla? tesla) - => TeslaByRoom.TryGetValue(room.Base, out tesla); } \ No newline at end of file diff --git a/LabApi/Features/Wrappers/Facility/Map.cs b/LabApi/Features/Wrappers/Facility/Map.cs index 67a0cd18..bf5befb0 100644 --- a/LabApi/Features/Wrappers/Facility/Map.cs +++ b/LabApi/Features/Wrappers/Facility/Map.cs @@ -3,6 +3,7 @@ using System; using System.Collections.Generic; using System.Linq; +using UnityEngine; namespace LabApi.Features.Wrappers; @@ -61,12 +62,40 @@ public static class Map ///
public static IReadOnlyCollection Ragdolls => Ragdoll.List; + /// + /// Represents the bounds for the default escape zone on surface. + /// + /// + /// By default this is included in the list. + /// + public static Bounds DefaultEscapeZone { get; } = Escape.DefaultEscapeZone; + + /// + /// A list of all bounds used as escape zones. + /// + /// + /// By default only the is included in the list. + /// + public static List EscapeZones => Escape.EscapeZones; + + /// + /// Adds another bounds to be used as an escape zone to the list. + /// + /// The bounds of the new escape zone. + public static void AddEscapeZone(Bounds escapeZone) => EscapeZones.Add(escapeZone); + + /// + /// Removes an existing bounds from the list. + /// + /// The bounds of the escape zone to remove. + public static void RemoveEscapeZone(Bounds escapeZone) => EscapeZones.Remove(escapeZone); #region Get Random + /// /// Gets a random . /// - /// The random room if there were any rooms otherwise null. + /// The random room if there were any rooms otherwise see langword="null"/>. public static Room? GetRandomRoom() { return Rooms.Count != 0 ? Rooms.ElementAt(UnityEngine.Random.Range(0, Rooms.Count)) : null; @@ -341,7 +370,9 @@ public static class Map public static void TurnOffLights(float duration) { foreach (LightsController lc in LightsController.List) + { lc.FlickerLights(duration); + } } /// @@ -355,11 +386,13 @@ public static void TurnOffLights(float duration) /// The zone to turn the lights off in. public static void TurnOffLights(FacilityZone zone) { - //TODO: use zone wrapper? + // TODO: use zone wrapper? foreach (LightsController lc in LightsController.List) { if (lc.Room.Zone != zone) + { continue; + } lc.FlickerLights(float.MaxValue); } @@ -371,17 +404,20 @@ public static void TurnOffLights(FacilityZone zone) /// The zones to turn off the lights. public static void TurnOffLights(IEnumerable zones) { + IEnumerable facilityZones = zones as FacilityZone[] ?? zones.ToArray(); + // TODO: use zone wrapper. foreach (LightsController lc in LightsController.List) { - if (!zones.Contains(lc.Room.Zone)) + if (!facilityZones.Contains(lc.Room.Zone)) + { continue; + } lc.FlickerLights(float.MaxValue); } } - /// /// Turns off all lights in a zone for a certain duration. /// @@ -393,7 +429,9 @@ public static void TurnOffLights(float duration, FacilityZone zone) foreach (LightsController lc in LightsController.List) { if (lc.Room.Zone != zone) + { continue; + } lc.FlickerLights(duration); } @@ -410,7 +448,9 @@ public static void TurnOffLights(float duration, IEnumerable zones foreach (LightsController lc in LightsController.List) { if (!zones.Contains(lc.Room.Zone)) + { continue; + } lc.FlickerLights(duration); } @@ -422,7 +462,9 @@ public static void TurnOffLights(float duration, IEnumerable zones public static void TurnOnLights() { foreach (LightsController lc in LightsController.List) + { lc.LightsEnabled = true; + } } /// @@ -435,7 +477,9 @@ public static void TurnOnLights(FacilityZone zone) foreach (LightsController lc in LightsController.List) { if (lc.Room.Zone != zone) + { continue; + } lc.LightsEnabled = true; } @@ -451,7 +495,9 @@ public static void TurnOnLights(IEnumerable zones) foreach (LightsController lc in LightsController.List) { if (!zones.Contains(lc.Room.Zone)) + { continue; + } lc.LightsEnabled = true; } @@ -466,7 +512,9 @@ public static void TurnOnLights(IEnumerable zones) public static void SetColorOfLights(UnityEngine.Color color) { foreach (LightsController lc in LightsController.List) + { lc.OverrideLightsColor = color; + } } /// @@ -480,7 +528,9 @@ public static void SetColorOfLights(UnityEngine.Color color, FacilityZone zone) foreach (LightsController lc in LightsController.List) { if (lc.Room.Zone != zone) + { continue; + } lc.OverrideLightsColor = color; } @@ -497,7 +547,9 @@ public static void SetColorOfLights(UnityEngine.Color color, IEnumerable - /// Sets the color of all the lights in a zone back to their default; + /// Sets the color of all the lights in a zone back to their default. /// /// The zone to effect. public static void ResetColorOfLights(FacilityZone zone) @@ -522,7 +576,9 @@ public static void ResetColorOfLights(FacilityZone zone) foreach (LightsController lc in LightsController.List) { if (lc.Room.Zone != zone) + { continue; + } lc.OverrideLightsColor = UnityEngine.Color.clear; } @@ -538,7 +594,9 @@ public static void ResetColorOfLights(IEnumerable zones) foreach (LightsController lc in LightsController.List) { if (!zones.Contains(lc.Room.Zone)) + { continue; + } lc.OverrideLightsColor = UnityEngine.Color.clear; } diff --git a/LabApi/Features/Wrappers/Facility/Respawning/RespawnWaves.cs b/LabApi/Features/Wrappers/Facility/Respawning/RespawnWaves.cs index 323b1379..ec689e05 100644 --- a/LabApi/Features/Wrappers/Facility/Respawning/RespawnWaves.cs +++ b/LabApi/Features/Wrappers/Facility/Respawning/RespawnWaves.cs @@ -1,6 +1,6 @@ -using Respawning; +using Generators; +using Respawning; using Respawning.Waves; -using Generators; namespace LabApi.Features.Wrappers; @@ -29,16 +29,6 @@ public static class RespawnWaves /// public static MiniChaosWave? MiniChaosWave { get; private set; } - /// - /// Initializes the wrapper and its wave wrapper instances. - /// - [InitializeWrapper] - internal static void Initialize() - { - foreach (SpawnableWaveBase wave in WaveManager.Waves) - Get(wave); - } - /// /// Gets the respawn wave wrapper from the static references or creates a new one if it doesn't exist and the provided was not or not valid subclass. /// @@ -55,5 +45,16 @@ internal static void Initialize() _ => null, }; } -} + /// + /// Initializes the wrapper and its wave wrapper instances. + /// + [InitializeWrapper] + internal static void Initialize() + { + foreach (SpawnableWaveBase wave in WaveManager.Waves) + { + Get(wave); + } + } +} diff --git a/LabApi/Features/Wrappers/Facility/Respawning/Waves/ChaosWave.cs b/LabApi/Features/Wrappers/Facility/Respawning/Waves/ChaosWave.cs index e7295052..d6389454 100644 --- a/LabApi/Features/Wrappers/Facility/Respawning/Waves/ChaosWave.cs +++ b/LabApi/Features/Wrappers/Facility/Respawning/Waves/ChaosWave.cs @@ -8,18 +8,20 @@ namespace LabApi.Features.Wrappers; /// public class ChaosWave : RespawnWave { - /// - internal ChaosWave(ChaosSpawnWave wave) : base(wave) + /// + internal ChaosWave(ChaosSpawnWave wave) + : base(wave) { Base = wave; } + /// /// The base object. /// public new ChaosSpawnWave Base { get; private set; } /// - /// Percentage of chaos supressors per wave. + /// Percentage of chaos suppressors per wave. /// public float LogicerPercent { @@ -44,8 +46,9 @@ public override int MaxWaveSize { float percentageValue = (float)value / ReferenceHub.AllHubs.Count; if (Base.Configuration is PrimaryWaveConfig config) + { config.SizePercentage = percentageValue; + } } } } - diff --git a/LabApi/Features/Wrappers/Facility/Respawning/Waves/MiniChaosWave.cs b/LabApi/Features/Wrappers/Facility/Respawning/Waves/MiniChaosWave.cs index dde945a3..d1a8fd84 100644 --- a/LabApi/Features/Wrappers/Facility/Respawning/Waves/MiniChaosWave.cs +++ b/LabApi/Features/Wrappers/Facility/Respawning/Waves/MiniChaosWave.cs @@ -7,12 +7,13 @@ namespace LabApi.Features.Wrappers; ///
public class MiniChaosWave : MiniRespawnWave { - /// - internal MiniChaosWave(ChaosMiniWave miniWave) : base(miniWave) + /// + internal MiniChaosWave(ChaosMiniWave miniWave) + : base(miniWave) { Base = miniWave; } - /// + /// public new ChaosMiniWave Base { get; private set; } } diff --git a/LabApi/Features/Wrappers/Facility/Respawning/Waves/MiniMtfWave.cs b/LabApi/Features/Wrappers/Facility/Respawning/Waves/MiniMtfWave.cs index d7f85c8d..2939edf4 100644 --- a/LabApi/Features/Wrappers/Facility/Respawning/Waves/MiniMtfWave.cs +++ b/LabApi/Features/Wrappers/Facility/Respawning/Waves/MiniMtfWave.cs @@ -7,13 +7,13 @@ namespace LabApi.Features.Wrappers; ///
public class MiniMtfWave : MiniRespawnWave { - /// - internal MiniMtfWave(NtfMiniWave miniWave) : base(miniWave) + /// + internal MiniMtfWave(NtfMiniWave miniWave) + : base(miniWave) { Base = miniWave; } - /// + /// public new NtfMiniWave Base { get; private set; } } - diff --git a/LabApi/Features/Wrappers/Facility/Respawning/Waves/MiniRespawnWave.cs b/LabApi/Features/Wrappers/Facility/Respawning/Waves/MiniRespawnWave.cs index bea28b4f..0008344e 100644 --- a/LabApi/Features/Wrappers/Facility/Respawning/Waves/MiniRespawnWave.cs +++ b/LabApi/Features/Wrappers/Facility/Respawning/Waves/MiniRespawnWave.cs @@ -12,7 +12,8 @@ public abstract class MiniRespawnWave : RespawnWave /// Internal constructor preventing external instantiation. ///
/// The base game object. - internal MiniRespawnWave(IMiniWave miniWave) : base((TimeBasedWave)miniWave) + internal MiniRespawnWave(IMiniWave miniWave) + : base((TimeBasedWave)miniWave) { Base = miniWave; } @@ -28,14 +29,19 @@ public override int MaxWaveSize get { if (Base is TimeBasedWave baseWave) + { return baseWave.MaxWaveSize; + } return 0; } + set { if (value < 0) + { return; + } float percentageValue = (float)value / ReferenceHub.AllHubs.Count; Base.WaveSizeMultiplier = percentageValue; @@ -77,4 +83,3 @@ public override void InitiateRespawn() ///
public virtual void Lock() => Base.ResetTokens(); } - diff --git a/LabApi/Features/Wrappers/Facility/Respawning/Waves/MtfWave.cs b/LabApi/Features/Wrappers/Facility/Respawning/Waves/MtfWave.cs index b4e7c58f..2d461d61 100644 --- a/LabApi/Features/Wrappers/Facility/Respawning/Waves/MtfWave.cs +++ b/LabApi/Features/Wrappers/Facility/Respawning/Waves/MtfWave.cs @@ -1,5 +1,7 @@ -using Respawning.Config; +using LabApi.Features.Console; +using Respawning.Config; using Respawning.Waves; +using System; namespace LabApi.Features.Wrappers; @@ -8,8 +10,9 @@ namespace LabApi.Features.Wrappers; ///
public class MtfWave : RespawnWave { - /// - internal MtfWave(NtfSpawnWave wave) : base(wave) + /// + internal MtfWave(NtfSpawnWave wave) + : base(wave) { Base = wave; } @@ -22,19 +25,39 @@ internal MtfWave(NtfSpawnWave wave) : base(wave) /// /// Gets or sets the amount of sergeants that can spawn with the wave. /// + [Obsolete("Use SergeantsPercentage instead", true)] public int MaxSergeants { - get => Base.MaxSergeants; - set => Base.MaxSergeants = value; + get => 0; + set => Logger.Error("Plugin Error. Cannot set MaxSergeants, use SergeantsPercentage instead."); + } + + /// + /// Gets the percentage of sergeants that can spawn with the wave. + /// + public float SergeantsPercentage + { + get => Base.SergeantPercent; + set => Base.SergeantPercent = value; } /// /// Gets or sets the amount of captains that can spawn with the wave. /// + [Obsolete("Use CaptainsPercentage instead", true)] public int MaxCaptains { - get => Base.MaxCaptains; - set => Base.MaxCaptains = value; + get => 0; + set => Logger.Error("Plugin Error. Cannot set MaxCaptains, use CaptainsPercentage instead."); + } + + /// + /// Gets the percentage of captains that can spawn with the wave. + /// + public float CaptainsPercentage + { + get => Base.CaptainPercent; + set => Base.CaptainPercent = value; } /// @@ -45,7 +68,9 @@ public override int MaxWaveSize { float percentageValue = (float)value / ReferenceHub.AllHubs.Count; if (Base.Configuration is PrimaryWaveConfig config) + { config.SizePercentage = percentageValue; + } } } } \ No newline at end of file diff --git a/LabApi/Features/Wrappers/Facility/Respawning/Waves/RespawnWave.cs b/LabApi/Features/Wrappers/Facility/Respawning/Waves/RespawnWave.cs index 3f4bc79a..04b2cd0a 100644 --- a/LabApi/Features/Wrappers/Facility/Respawning/Waves/RespawnWave.cs +++ b/LabApi/Features/Wrappers/Facility/Respawning/Waves/RespawnWave.cs @@ -1,4 +1,7 @@ -using PlayerRoles; +using System; +using System.Collections.Generic; +using System.Linq; +using PlayerRoles; using Respawning; using Respawning.Config; using Respawning.Waves; @@ -53,7 +56,9 @@ public float AnimationTime get { if (Base is IAnimatedWave wave) + { return wave.AnimationDuration; + } return 0f; } @@ -67,16 +72,21 @@ public int RespawnTokens get { if (Base is ILimitedWave wave) + { return wave.RespawnTokens; + } return 0; } + set { if (Base is not ILimitedWave wave) + { return; + } - wave.InitialRespawnTokens = value; + wave.RespawnTokens = value; WaveUpdateMessage.ServerSendUpdate(Base, UpdateMessageFlags.Tokens); } } @@ -96,12 +106,15 @@ public float Influence public float TimeLeft { get => Base.Timer.TimeLeft; - set => Base.Timer.SetTime(value); + set => Base.Timer.SetTime(Base.Timer.SpawnIntervalSeconds - value); } /// /// Gets or sets the time this wave's timer is paused. /// + /// + /// Currently the wave timer pauses only at about 10% left. + /// public float PausedTime { get => Base.Timer.PauseTimeLeft; @@ -114,12 +127,12 @@ public float PausedTime public float TimePassed => Base.Timer.TimePassed; /// - /// Attempts to get milestone for next . + /// Attempts to get milestone for next . /// Returns if this has maximum influence possible. /// - /// Out param containing next target influence. + /// Out param containing next target influence. /// Whether there is next available milestone. - public bool TryGetCurrentMilestone(out int influenceTreshold) => RespawnTokensManager.TryGetNextThreshold(Faction, Influence, out influenceTreshold); + public bool TryGetCurrentMilestone(out int influenceThreshold) => RespawnTokensManager.TryGetNextThreshold(Faction, Influence, out influenceThreshold); /// /// Initiates the respawn with animation. @@ -134,9 +147,34 @@ public float PausedTime /// /// Plays the respawn announcement. /// + [Obsolete("Use PlayAnnouncement(IEnumerable) instead.", true)] public void PlayAnnouncement() + { + PlayAnnouncement([]); + } + + /// + /// Plays the respawn announcement. + /// + /// The players that have spawned to take into account for the announcement. + public void PlayAnnouncement(IEnumerable spawnedPlayers) { if (Base is IAnnouncedWave wave) - wave.Announcement.PlayAnnouncement(); + { + wave.Announcement.PlayAnnouncement(spawnedPlayers.Select(p => p.ReferenceHub).ToList(), wave); + } + } + + /// + /// Plays the respawn animation without spawning the wave. + /// + public void PlayRespawnEffect() + { + if (Base is not IAnimatedWave) + { + return; + } + + WaveUpdateMessage.ServerSendUpdate(Base, UpdateMessageFlags.Trigger); } } diff --git a/LabApi/Features/Wrappers/Facility/Rooms/Camera.cs b/LabApi/Features/Wrappers/Facility/Rooms/Camera.cs index a5eac553..d28a1d9a 100644 --- a/LabApi/Features/Wrappers/Facility/Rooms/Camera.cs +++ b/LabApi/Features/Wrappers/Facility/Rooms/Camera.cs @@ -1,7 +1,7 @@ -using PlayerRoles.PlayableScps.Scp079.Cameras; +using Generators; +using PlayerRoles.PlayableScps.Scp079.Cameras; using System.Collections.Generic; using System.Diagnostics.CodeAnalysis; -using Generators; using UnityEngine; namespace LabApi.Features.Wrappers; @@ -22,7 +22,35 @@ public class Camera public static IReadOnlyCollection List => Dictionary.Values; /// - /// Initializes the class to subscribe to + /// Gets the associated with the . + /// + /// The to get the camera from. + /// The associated with the or if it doesn't exist. + [return: NotNullIfNotNull(nameof(camera))] + public static Camera? Get(Scp079Camera? camera) + { + if (camera == null) + { + return null; + } + + return TryGet(camera, out Camera? cam) ? cam : new Camera(camera); + } + + /// + /// Tries to get the associated with the . + /// + /// The to get the camera from. + /// The associated with the or if it doesn't exist. + /// Whether the camera was successfully retrieved. + public static bool TryGet(Scp079Camera camera, [NotNullWhen(true)] out Camera? wrapper) + { + wrapper = null; + return camera != null && Dictionary.TryGetValue(camera, out wrapper); + } + + /// + /// Initializes the class to subscribe to. /// [InitializeWrapper] internal static void Initialize() @@ -33,6 +61,15 @@ internal static void Initialize() Scp079Camera.OnInstanceRemoved += (camera) => Remove(camera); } + /// + /// Handles the removal of a camera from the dictionary. + /// + /// The camera to remove. + private static void Remove(Scp079Camera camera) + { + Dictionary.Remove(camera); + } + /// /// A private constructor to prevent external instantiation. /// @@ -91,39 +128,4 @@ public override string ToString() { return $"[Camera: Position={Position}, Rotation={Rotation}, Room={Room}, Zoom={Zoom}, IsBeingUsed={IsBeingUsed}]"; } - - /// - /// Gets the associated with the . - /// - /// The to get the camera from. - /// The associated with the or if it doesn't exist. - [return: NotNullIfNotNull(nameof(camera))] - public static Camera? Get(Scp079Camera? camera) - { - if (camera == null) - return null; - - return TryGet(camera, out Camera? cam) ? cam : new Camera(camera); - } - - /// - /// Tries to get the associated with the . - /// - /// The to get the camera from. - /// The associated with the or if it doesn't exist. - /// Whether the camera was successfully retrieved. - public static bool TryGet(Scp079Camera camera, [NotNullWhen(true)] out Camera? wrapper) - { - wrapper = null; - return camera != null && Dictionary.TryGetValue(camera, out wrapper); - } - - /// - /// Handles the removal of a camera from the dictionary. - /// - /// The camera to remove. - private static void Remove(Scp079Camera camera) - { - Dictionary.Remove(camera); - } } \ No newline at end of file diff --git a/LabApi/Features/Wrappers/Facility/Rooms/LightsController.cs b/LabApi/Features/Wrappers/Facility/Rooms/LightsController.cs index 01ede3af..dedba386 100644 --- a/LabApi/Features/Wrappers/Facility/Rooms/LightsController.cs +++ b/LabApi/Features/Wrappers/Facility/Rooms/LightsController.cs @@ -11,23 +11,29 @@ namespace LabApi.Features.Wrappers; public class LightsController { /// - /// Contains all the cached rooms in the game, accessible through their . + /// A reference to all instances currently in the game. /// - private static Dictionary Dictionary { get; } = []; + public static IReadOnlyCollection List => Dictionary.Values; /// - /// A reference to all instances currently in the game. + /// Contains all the cached rooms in the game, accessible through their . /// - public static IReadOnlyCollection List => Dictionary.Values; + private static Dictionary Dictionary { get; } = []; /// - /// A private constructor to prevent external instantiation. + /// Gets the controller wrapper from , or creates a new one if it doesn't exists. /// - /// The original object. - private LightsController(RoomLightController original) + /// The original light controller. + /// The requested light controller wrapper. + [return: NotNullIfNotNull(nameof(roomLightController))] + public static LightsController? Get(RoomLightController roomLightController) { - Dictionary.Add(original, this); - Base = original; + if (roomLightController == null) + { + return null; + } + + return Dictionary.TryGetValue(roomLightController, out LightsController lightController) ? lightController : new LightsController(roomLightController); } /// @@ -40,6 +46,16 @@ internal static void Initialize() RoomLightController.OnRemoved += (roomLightController) => Dictionary.Remove(roomLightController); } + /// + /// A private constructor to prevent external instantiation. + /// + /// The original object. + private LightsController(RoomLightController original) + { + Dictionary.Add(original, this); + Base = original; + } + /// /// The base game object. /// @@ -48,7 +64,7 @@ internal static void Initialize() /// /// The room this controller is assigned to. /// - public Room? Room => Room.Get(Base.Room); + public Room Room => Room.Get(Base.Room)!; /// /// Gets or sets whether the lights are enabled in this room. @@ -73,18 +89,4 @@ public Color OverrideLightsColor /// /// Duration of light shutdown in seconds. public void FlickerLights(float duration) => Base.ServerFlickerLights(duration); - - /// - /// Gets the controller wrapper from , or creates a new one if it doesnt exists. - /// - /// The original light controller. - /// The requested light controller wrapper. - [return: NotNullIfNotNull(nameof(roomLightController))] - public static LightsController? Get(RoomLightController roomLightController) - { - if (roomLightController == null) - return null; - - return Dictionary.TryGetValue(roomLightController, out LightsController lightController) ? lightController : new LightsController(roomLightController); - } } \ No newline at end of file diff --git a/LabApi/Features/Wrappers/Facility/Rooms/PocketDimension/PocketDimension.cs b/LabApi/Features/Wrappers/Facility/Rooms/PocketDimension/PocketDimension.cs index db00d949..de4d55c3 100644 --- a/LabApi/Features/Wrappers/Facility/Rooms/PocketDimension/PocketDimension.cs +++ b/LabApi/Features/Wrappers/Facility/Rooms/PocketDimension/PocketDimension.cs @@ -48,7 +48,7 @@ public static float MinPocketItemTriggerDelay get => Scp106PocketItemManager.TimerRange.x; set => Scp106PocketItemManager.TimerRange = Scp106PocketItemManager.TimerRange with { - x = value + x = value, }; } @@ -60,30 +60,10 @@ public static float MaxPocketItemTriggerDelay get => Scp106PocketItemManager.TimerRange.y; set => Scp106PocketItemManager.TimerRange = Scp106PocketItemManager.TimerRange with { - y = value + y = value, }; } - /// - /// An internal constructor to prevent external instantiation. - /// - /// The room identifier for the pocket dimension. - internal PocketDimension(RoomIdentifier room) - : base(room) - { - if (CanCache) - Instance = this; - } - - /// - /// An internal method to set the instance to null when the base object is destroyed. - /// - internal override void OnRemoved() - { - base.OnRemoved(); - Instance = null; - } - /// /// Force a inside the pocket dimension. /// @@ -97,6 +77,23 @@ internal override void OnRemoved() /// True if inside otherwise false. public static bool IsPlayerInside(Player player) => player.HasEffect(); + /// + /// Gets the position at which the was caught. + /// + /// The player. + /// Returns caught position, also returns if the player is not in . + public static Vector3 GetCaughtPosition(Player player) + { + PocketCorroding? effect = player.GetEffect(); + + if (effect != null && effect.Intensity > 0) + { + return effect.CapturePosition.Position; + } + + return Vector3.zero; + } + /// /// Force a player to exit the pocket dimension. /// @@ -106,7 +103,7 @@ internal override void OnRemoved() /// Triggers pocket dimension leaving/left events. /// public static void ForceExit(Player player) - => PocketDimensionTeleport.Exit(null, player.ReferenceHub); + => PocketDimensionTeleport.TryExit(null, player.ReferenceHub); /// /// Force a player to be killed by the pocket dimension. @@ -117,7 +114,7 @@ public static void ForceExit(Player player) /// Triggers pocket dimension leaving/left events. /// public static void ForceKill(Player player) - => PocketDimensionTeleport.Kill(null, player.ReferenceHub); + => PocketDimensionTeleport.TryKill(null, player.ReferenceHub); /// /// Gets whether a is inside the pocket dimension. @@ -128,7 +125,7 @@ public static bool IsPickupInside(Pickup pickup) => Scp106PocketItemManager.TrackedItems.ContainsKey(pickup.Base); /// - /// Randomizes which pocket dimension's teleports are exits. + /// Randomizes which pocket dimension's teleports are exits. /// public static void RandomizeExits() => PocketDimensionGenerator.RandomizeTeleports(); @@ -149,9 +146,11 @@ public static void AddExitPosesForZone(FacilityZone zone, IEnumerable pose { // Attempts to generate the pose array as it could be empty. if (!Scp106PocketExitFinder.PosesForZoneCache.ContainsKey(zone)) + { Scp106PocketExitFinder.GetPosesForZone(zone); + } - Scp106PocketExitFinder.PosesForZoneCache[zone] = Scp106PocketExitFinder.PosesForZoneCache[zone].Concat(poses).ToArray(); + Scp106PocketExitFinder.PosesForZoneCache[zone] = [.. Scp106PocketExitFinder.PosesForZoneCache[zone], .. poses]; } /// @@ -167,7 +166,7 @@ public static void AddExitPosesForZone(FacilityZone zone, IEnumerable pose /// The zone to remove exits from. public static void RemoveAllExitPosesForZone(FacilityZone zone) => Scp106PocketExitFinder.PosesForZoneCache[zone] = []; - + /// /// Removes the specified poses from use as exits for the pocket dimension. /// @@ -177,7 +176,9 @@ public static void RemoveExitPosesForZone(FacilityZone zone, IEnumerable p { // Attempts to generate the pose array as it could be empty. if (!Scp106PocketExitFinder.PosesForZoneCache.ContainsKey(zone)) + { Scp106PocketExitFinder.GetPosesForZone(zone); + } Scp106PocketExitFinder.PosesForZoneCache[zone] = Scp106PocketExitFinder.PosesForZoneCache[zone].Except(poses).ToArray(); } @@ -211,4 +212,26 @@ public static int GetRarity(Pickup pickup) /// The rarity of the item. public static int GetRarity(ItemBase item) => Scp106PocketItemManager.GetRarity(item); + + /// + /// An internal constructor to prevent external instantiation. + /// + /// The room identifier for the pocket dimension. + internal PocketDimension(RoomIdentifier room) + : base(room) + { + if (CanCache) + { + Instance = this; + } + } + + /// + /// An internal method to set the instance to null when the base object is destroyed. + /// + internal override void OnRemoved() + { + base.OnRemoved(); + Instance = null; + } } diff --git a/LabApi/Features/Wrappers/Facility/Rooms/PocketDimension/PocketItem.cs b/LabApi/Features/Wrappers/Facility/Rooms/PocketDimension/PocketItem.cs index 161be7b1..fc9b9155 100644 --- a/LabApi/Features/Wrappers/Facility/Rooms/PocketDimension/PocketItem.cs +++ b/LabApi/Features/Wrappers/Facility/Rooms/PocketDimension/PocketItem.cs @@ -18,6 +18,52 @@ namespace LabApi.Features.Wrappers; /// public class PocketItem { + /// + /// Contains all the cached instances, accessible through their . + /// + private static readonly Dictionary Dictionary = []; + + /// + /// A reference to all instances currently in the game. + /// + public static IReadOnlyCollection List => Dictionary.Values; + + /// + /// Tries to get the associated with the . + /// + /// The inside the pocket dimension to get the from. + /// The associated with or null if it doesn't exists. + /// Whether the was successfully retrieved. + public static bool TryGet(Pickup pickup, [NotNullWhen(true)] out PocketItem? pocketItem) + => Dictionary.TryGetValue(pickup.Base, out pocketItem); + + /// + /// Gets the associated with the . + /// + /// The inside the pocket dimension to get the from. + /// The associated for the or null if it doesn't exist. + public static PocketItem? Get(Pickup pickup) => TryGet(pickup, out PocketItem? pocketItem) ? pocketItem : null; + + /// + /// Gets or adds a . + /// + /// The to get or add to the pocket dimension. + /// The instance. + /// + /// If the pickup is not in the pocket dimension it is teleported there on creation of the . + /// + public static PocketItem GetOrAdd(Pickup pickup) + { + if (Dictionary.TryGetValue(pickup.Base, out PocketItem? pocketItem)) + { + return pocketItem; + } + + pickup.Position = PocketDimension.Instance!.Position + Vector3.up; + Scp106PocketItemManager.AddItem(pickup.Base); + return Get(pickup)!; + } + /// /// Initializes the PocketItem wrapper by subscribing to the PocketDimensionTeleport events. /// @@ -28,16 +74,6 @@ internal static void Initialize() Scp106PocketItemManager.OnPocketItemRemoved += (itemPickupBase) => Dictionary.Remove(itemPickupBase); } - /// - /// Contains all the cached instances, accessible through their . - /// - private static Dictionary Dictionary = []; - - /// - /// A reference to all instances currently in the game. - /// - public static IReadOnlyCollection List => Dictionary.Values; - /// /// An internal constructor to prevent external instantiation. /// @@ -88,41 +124,7 @@ public Vector3 DropPosition } /// - /// Gets whether a warning cue was sent to the players about a dropping item pickup. + /// Gets whether a warning cue was sent to the players about a dropping item pickup. /// public bool IsWarningSent => Base.WarningSent; - - /// - /// Tries to get the associated with the . - /// - /// The inside the pocket dimension to get the from. - /// The associated with or null if it doesn't exists. - /// Whether the was successfully retrieved. - public static bool TryGet(Pickup pickup, [NotNullWhen(true)] out PocketItem? pocketItem) - => Dictionary.TryGetValue(pickup.Base, out pocketItem); - - /// - /// Gets the associated with the . - /// - /// The inside the pocket dimension to get the from. - /// The associated for the or null if it doesn't exist. - public static PocketItem? Get(Pickup pickup) => TryGet(pickup, out PocketItem? pocketItem) ? pocketItem : null; - - /// - /// Gets or adds a . - /// - /// The to get or add to the pocket dimension. - /// The instance. - /// - /// If the pickup is not in the pocket dimension it is teleported there on creation of the . - /// - public static PocketItem GetOrAdd(Pickup pickup) - { - if (Dictionary.TryGetValue(pickup.Base, out PocketItem? pocketItem)) - return pocketItem; - - pickup.Position = PocketDimension.Instance!.Position + Vector3.up; - Scp106PocketItemManager.AddItem(pickup.Base); - return Get(pickup)!; - } } diff --git a/LabApi/Features/Wrappers/Facility/Rooms/PocketDimension/PocketTeleport.cs b/LabApi/Features/Wrappers/Facility/Rooms/PocketDimension/PocketTeleport.cs index 46160e95..2bd897dc 100644 --- a/LabApi/Features/Wrappers/Facility/Rooms/PocketDimension/PocketTeleport.cs +++ b/LabApi/Features/Wrappers/Facility/Rooms/PocketDimension/PocketTeleport.cs @@ -11,6 +11,37 @@ namespace LabApi.Features.Wrappers; /// public class PocketTeleport { + /// + /// A reference to all instances currently in the game. + /// + public static IReadOnlyCollection List => Dictionary.Values; + + /// + /// Contains all the cached teleports in the game, accessible through their . + /// + private static Dictionary Dictionary { get; } = []; + + /// + /// Gets the wrapper given the base game instance. + /// + /// The base game object. + /// The associated wrapper. + [return: NotNullIfNotNull(nameof(pocketTeleport))] + public static PocketTeleport? Get(PocketDimensionTeleport? pocketTeleport) + { + if (pocketTeleport == null) + { + return null; + } + + if (Dictionary.TryGetValue(pocketTeleport, out PocketTeleport pt)) + { + return pt; + } + + return new PocketTeleport(pocketTeleport); + } + /// /// Initializes the Teleport wrapper by subscribing to the PocketDimensionTeleport events. /// @@ -22,14 +53,25 @@ internal static void Initialize() } /// - /// Contains all the cached teleports in the game, accessible through their . + /// A private method to handle the addition of instances. /// - private static Dictionary Dictionary { get; } = []; + /// The base game instance. + private static void OnAdded(PocketDimensionTeleport pocketTeleport) + { + if (!Dictionary.ContainsKey(pocketTeleport)) + { + _ = new PocketTeleport(pocketTeleport); + } + } /// - /// A reference to all instances currently in the game. + /// A private method to handle the removal of instances. /// - public static IReadOnlyCollection List => Dictionary.Values; + /// The base game instance. + private static void OnRemoved(PocketDimensionTeleport pocketTeleport) + { + Dictionary.Remove(pocketTeleport); + } /// /// An internal constructor to prevent external instantiation. @@ -113,6 +155,8 @@ public float Radius /// /// Spawns a new pocket teleport. /// + /// The position relative to the pocket dimension. + /// The created . public PocketTeleport Spawn(Vector3 localPosition) { GameObject obj = new("Teleport", typeof(PocketDimensionTeleport), typeof(SphereCollider), typeof(NetworkIdentity)); @@ -125,41 +169,4 @@ public PocketTeleport Spawn(Vector3 localPosition) /// Destroys the removing it from the server. /// public void Destroy() => Object.Destroy(Base); - - /// - /// Gets the wrapper given the base game instance. - /// - /// The base game object. - /// The associated wrapper. - [return: NotNullIfNotNull(nameof(pocketTeleport))] - public static PocketTeleport? Get(PocketDimensionTeleport? pocketTeleport) - { - if(pocketTeleport == null) - return null; - - if (Dictionary.TryGetValue(pocketTeleport, out PocketTeleport pt)) - return pt; - - return new PocketTeleport(pocketTeleport); - } - - /// - /// A private method to handle the addition of instances. - /// - /// The base game instance. - private static void OnAdded(PocketDimensionTeleport pocketTeleport) - { - if (!Dictionary.ContainsKey(pocketTeleport)) - _ = new PocketTeleport(pocketTeleport); - } - - /// - /// A private method to handle the removal of instances. - /// - /// The base game instance. - private static void OnRemoved(PocketDimensionTeleport pocketTeleport) - { - Dictionary.Remove(pocketTeleport); - } } - diff --git a/LabApi/Features/Wrappers/Facility/Rooms/Room.cs b/LabApi/Features/Wrappers/Facility/Rooms/Room.cs index 0f9b2011..04c7e1d3 100644 --- a/LabApi/Features/Wrappers/Facility/Rooms/Room.cs +++ b/LabApi/Features/Wrappers/Facility/Rooms/Room.cs @@ -1,10 +1,13 @@ using Generators; using Interactables.Interobjects.DoorUtils; +using LabApi.Features.Extensions; using MapGeneration; +using System; using System.Collections.Generic; using System.Diagnostics.CodeAnalysis; using System.Linq; using UnityEngine; +using UnityEngine.Pool; namespace LabApi.Features.Wrappers; @@ -13,20 +16,10 @@ namespace LabApi.Features.Wrappers; /// public class Room { - /// - /// Initializes the Room wrapper by subscribing to the RoomIdentifier events. - /// - [InitializeWrapper] - internal static void Initialize() - { - RoomIdentifier.OnAdded += AddRoom; - RoomIdentifier.OnRemoved += RemoveRoom; - } - /// /// Contains all the cached rooms in the game, accessible through their . /// - private static Dictionary Dictionary { get; } = []; + public static Dictionary Dictionary { get; } = []; /// /// A reference to all instances currently in the game. @@ -34,118 +27,96 @@ internal static void Initialize() public static IReadOnlyCollection List => Dictionary.Values; /// - /// An internal constructor to prevent external instantiation. - /// - /// The identifier of the room. - internal Room(RoomIdentifier roomIdentifier) - { - Base = roomIdentifier; - - if (CanCache) - Dictionary.Add(roomIdentifier, this); - } - - /// - /// An internal virtual method to signal to derived wrappers that the base has been destroyed. + /// Gets path from to .
+ /// Path is found via Dijkstra's algorithm. Path still works between zones (including via elevators) as it uses .
+ /// If no path is found, an empty list is returned. ///
- internal virtual void OnRemoved() + /// The starting room. + /// The ending room. + /// The weight function to calculate cost to the next room. Can be change if you prefer to go around tesla gates and such. + /// A pooled list containing rooms from to (including these rooms). + public static List FindPath(Room start, Room end, Func weightFunction) { - Dictionary.Remove(Base); - } + List path = NorthwoodLib.Pools.ListPool.Shared.Rent(); - /// - /// The base object. - /// - public RoomIdentifier Base { get; } - - /// - /// Gets whether the base room instance was destroyed. - /// - public bool IsDestroyed => Base == null || GameObject == null; - - /// - /// The room's shape. - /// - public RoomShape Shape => Base.Shape; - - /// - /// The room's name. - /// - public RoomName Name => Base.Name; - - /// - /// The zone in which this room is located. - /// - public FacilityZone Zone => Base.Zone; - - /// - /// Gets the room's neighbors. - /// - public HashSet ConnectedRooms => Base.ConnectedRooms; - - /// - /// Gets the doors that are a part of this room. TODO: Cache in base game code? - /// - public IEnumerable Doors - { - get + if (start == null || end == null || start == end) { - return DoorVariant.DoorsByRoom.TryGetValue(Base, out HashSet doors) ? doors.Where(x => x != null).Select(x => Door.Get(x!)) : []; + return path; } - } - /// - /// Gets the first light controller for this room.

- /// Please see if you wish to modify all lights in this room. - ///
- public LightsController? LightController => Base.LightControllers.Count > 0 ? LightsController.Get(Base.LightControllers[0]) : null; + Dictionary previous = DictionaryPool.Get(); + Dictionary distances = DictionaryPool.Get(); + HashSet visited = NorthwoodLib.Pools.HashSetPool.Shared.Rent(); + PriorityQueue queue = PriorityQueuePool.Shared.Rent(); - /// - /// Gets all light controllers for this specified room.
- /// Some rooms such as 049, warhead and etc may have multiple light controllers as they are split by the elevator. - ///
- public IEnumerable AllLightControllers => Base.LightControllers.Select(LightsController.Get); + // Standard dijakstra + foreach (Room room in List) + { + distances[room] = int.MaxValue; + previous[room] = null; + } - /// - /// Gets the room's . - /// - public Transform Transform => Base.transform; + distances[start] = 0; + queue.Enqueue(start, 0); - /// - /// Gets the room's . - /// - public GameObject GameObject => Base.gameObject; + while (queue.Count > 0) + { + Room current = queue.Dequeue(); + + if (visited.Contains(current)) + { + continue; + } + + visited.Add(current); + + if (current == end) + { + break; + } + + foreach (Room neighbor in current.AdjacentRooms) + { + if (visited.Contains(neighbor)) + { + continue; + } + + int newDistance = distances[current] + weightFunction(neighbor); + if (newDistance < distances[neighbor]) + { + distances[neighbor] = newDistance; + previous[neighbor] = current; + queue.Enqueue(neighbor, newDistance); + } + } + } - /// - /// Gets the room's position. - /// - public Vector3 Position => Transform.position; + Room? step = end; - /// - /// Gets the room's rotation. - /// - public Quaternion Rotation => Transform.rotation; + // Reconstruct the path from start to end room + while (step != null) + { + path.Insert(0, step); + step = previous[step]; + } - /// - /// Gets a collection of players in the room. - /// - public IEnumerable Players => Player.List.Where(p => p.Room == this); + // If only entry is the end room, clear the path as it wasn't found + if (path.Count == 1 && path[0] == end) + { + path.Clear(); + } - /// - /// Gets a collection of cameras in the room. - /// - public IEnumerable Cameras => Camera.List.Where(x => x.Room == this); + DictionaryPool.Release(previous); + DictionaryPool.Release(distances); + NorthwoodLib.Pools.HashSetPool.Shared.Return(visited); + PriorityQueuePool.Shared.Return(queue); - /// - public override string ToString() - { - return $"[{GetType().Name}: Name={Name}, Shape={Shape}, Zone={Zone}]"; + return path; } - - /// - /// Gets whether the room wrapper is allowed to be cached. - /// - protected bool CanCache => !IsDestroyed; + + /// + public static List FindPath(Room start, Room end) => FindPath(start, end, static (room) => 1); /// /// Gets the room wrapper from the , or creates a new one if it doesn't exist. @@ -156,10 +127,14 @@ public override string ToString() public static Room? Get(RoomIdentifier? roomIdentifier) { if (roomIdentifier == null) + { return null; + } if (Dictionary.TryGetValue(roomIdentifier, out Room room)) + { return room; + } return CreateRoomWrapper(roomIdentifier); } @@ -194,18 +169,7 @@ public static IEnumerable Get(FacilityZone facilityZone) => /// The room identifiers to get the rooms from. /// The requested rooms. public static IEnumerable Get(IEnumerable roomIdentifiers) => - roomIdentifiers.Select(Get); - - /// - /// Gets the closest to the specified player. - /// - /// The player to check the closest light controller for. - /// The closest light controller. May return if player is not alive or is not in any room. - public LightsController? GetClosestLightController(Player player) - { - RoomLightController rlc = Base.GetClosestLightController(player.ReferenceHub); - return rlc == null ? null : LightsController.Get(rlc); - } + roomIdentifiers.Select(Get)!; /// /// Tries to get the room at the specified position. @@ -232,6 +196,16 @@ public static bool TryGetRoomAtPosition(Vector3 position, [NotNullWhen(true)] ou /// The room at the specified position or if no room was found. public static Room? GetRoomAtPosition(Vector3 position) => TryGetRoomAtPosition(position, out Room? room) ? room : null; + /// + /// Initializes the Room wrapper by subscribing to the RoomIdentifier events. + /// + [InitializeWrapper] + internal static void Initialize() + { + RoomIdentifier.OnAdded += AddRoom; + RoomIdentifier.OnRemoved += RemoveRoom; + } + /// /// Creates a new wrapper from the base room object. /// @@ -240,11 +214,17 @@ public static bool TryGetRoomAtPosition(Vector3 position, [NotNullWhen(true)] ou protected static Room CreateRoomWrapper(RoomIdentifier roomIdentifier) { if (roomIdentifier.Name == RoomName.Pocket) + { return new PocketDimension(roomIdentifier); + } else if (roomIdentifier.Name == RoomName.Lcz914) + { return new Scp914(roomIdentifier); + } else + { return new Room(roomIdentifier); + } } /// @@ -256,9 +236,11 @@ private static void AddRoom(RoomIdentifier roomIdentifier) try { if (!Dictionary.ContainsKey(roomIdentifier)) + { _ = CreateRoomWrapper(roomIdentifier); + } } - catch (System.Exception e) + catch (Exception e) { Console.Logger.InternalError($"Failed to handle room creation with error: {e}"); } @@ -273,11 +255,204 @@ private static void RemoveRoom(RoomIdentifier roomIdentifier) try { if (Dictionary.TryGetValue(roomIdentifier, out Room room)) + { room.OnRemoved(); + } } - catch (System.Exception e) + catch (Exception e) { Console.Logger.InternalError($"Failed to handle item destruction with error: {e}"); } } + + private IReadOnlyCollection? _adjacentRooms; + + /// + /// An internal constructor to prevent external instantiation. + /// + /// The identifier of the room. + internal Room(RoomIdentifier roomIdentifier) + { + Base = roomIdentifier; + + if (CanCache) + { + Dictionary.Add(roomIdentifier, this); + } + } + + /// + /// The base object. + /// + public RoomIdentifier Base { get; } + + /// + /// Gets whether the base room instance was destroyed. + /// + public bool IsDestroyed => Base == null || GameObject == null; + + /// + /// The room's shape. + /// + public RoomShape Shape => Base.Shape; + + /// + /// The room's name. + /// + public RoomName Name => Base.Name; + + /// + /// The zone in which this room is located. + /// + public FacilityZone Zone => Base.Zone; + + /// + /// Gets the room's neighbors. + /// + public HashSet ConnectedRooms => Base.ConnectedRooms; + + /// + /// Gets the room's adjacent rooms where the player can traverse to. + /// Includes rooms that can be traversed to via elevator. + /// + public IReadOnlyCollection AdjacentRooms + { + get + { + if (_adjacentRooms != null) + { + return _adjacentRooms; + } + + List rooms = [.. ConnectedRooms.Select(Get)]; + + // Check if the room has elevator + Elevator? target = null; + foreach (Elevator elevator in Elevator.List) + { + if (elevator.Rooms.Contains(this)) + { + target = elevator; + } + } + + // Add rooms that are on other floors of this elevator + if (target != null) + { + foreach (Room room in target.Rooms) + { + if (room == this) + { + continue; + } + + rooms.Add(room); + } + } + + // Hcz-Ez checkpoints + if (Name == RoomName.HczCheckpointToEntranceZone) + { + FacilityZone targetZone = Zone == FacilityZone.HeavyContainment ? FacilityZone.Entrance : FacilityZone.HeavyContainment; + + Room? match = List + .Where(n => n.Name == RoomName.HczCheckpointToEntranceZone && n.Zone == targetZone) + .MinBy(n => (n.Position - Position).sqrMagnitude); + + if (match != null) + { + rooms.Add(match); + } + } + + _adjacentRooms = rooms.AsReadOnly(); + return _adjacentRooms; + } + } + + /// + /// Gets the doors that are a part of this room. + /// + public IEnumerable Doors + { + get + { + return DoorVariant.DoorsByRoom.TryGetValue(Base, out HashSet doors) ? doors.Where(static x => x != null).Select(static x => Door.Get(x!)) : []; + } + } + + /// + /// Gets the first light controller for this room.
+ /// + /// Use if you wish to modify all lights in this room. + /// + ///
+ public LightsController? LightController => Base.LightControllers.Count > 0 ? LightsController.Get(Base.LightControllers[0]) : null; + + /// + /// Gets all light controllers for this specified room.
+ /// Some rooms such as 049, warhead and such may have multiple light controllers as they are split by the elevator. + ///
+ public IEnumerable AllLightControllers => Base.LightControllers.Select(LightsController.Get)!; + + /// + /// Gets the room's . + /// + public Transform Transform => Base.transform; + + /// + /// Gets the room's . + /// + public GameObject GameObject => Base.gameObject; + + /// + /// Gets the room's position. + /// + public Vector3 Position => Transform.position; + + /// + /// Gets the room's rotation. + /// + public Quaternion Rotation => Transform.rotation; + + /// + /// Gets a collection of players in the room. + /// + public IEnumerable Players => Player.List.Where(p => p.Room == this); + + /// + /// Gets a collection of cameras in the room. + /// + public IEnumerable Cameras => Camera.List.Where(x => x.Room == this); + + /// + /// Gets whether the room wrapper is allowed to be cached. + /// + protected bool CanCache => !IsDestroyed && Base.isActiveAndEnabled; + + /// + public override string ToString() + { + return $"[{GetType().Name}: Name={Name}, Shape={Shape}, Zone={Zone}]"; + } + + /// + /// Gets the closest to the specified player. + /// + /// The player to check the closest light controller for. + /// The closest light controller. May return if player is not alive or is not in any room. + public LightsController? GetClosestLightController(Player player) + { + RoomLightController rlc = Base.GetClosestLightController(player.ReferenceHub); + return rlc == null ? null : LightsController.Get(rlc); + } + + /// + /// An internal virtual method to signal to derived wrappers that the base has been destroyed. + /// + internal virtual void OnRemoved() + { + Dictionary.Remove(Base); + _adjacentRooms = null; + } } \ No newline at end of file diff --git a/LabApi/Features/Wrappers/Facility/Rooms/Scp914/BaseGameItemProcessor.cs b/LabApi/Features/Wrappers/Facility/Rooms/Scp914/BaseGameItemProcessor.cs index 7a42cefb..5bc42590 100644 --- a/LabApi/Features/Wrappers/Facility/Rooms/Scp914/BaseGameItemProcessor.cs +++ b/LabApi/Features/Wrappers/Facility/Rooms/Scp914/BaseGameItemProcessor.cs @@ -1,7 +1,6 @@ using LabApi.Features.Interfaces; using Scp914; using Scp914.Processors; -using UnityEngine; namespace LabApi.Features.Wrappers; diff --git a/LabApi/Features/Wrappers/Facility/Rooms/Scp914/IItemProcessor.cs b/LabApi/Features/Wrappers/Facility/Rooms/Scp914/IItemProcessor.cs deleted file mode 100644 index 24009f2c..00000000 --- a/LabApi/Features/Wrappers/Facility/Rooms/Scp914/IItemProcessor.cs +++ /dev/null @@ -1,36 +0,0 @@ -using Scp914; -using UnityEngine; - -namespace LabApi.Features.Wrappers; - -/// -/// An interface for creating custom SCP-914 Item upgrade processors. -/// -public interface IItemProcessor -{ - /// - /// Called for each players items in the intake chamber of SCP-914 if the allows so. - /// - /// The used for this upgrade. - /// The that owns this item. - /// The to upgraded. - /// The upgraded or null if it was destroyed. - /// - /// Use to remove items and to add items. - /// If adding extra Items over the limit of the inventory consider dropping them as pickups at the output. - /// - public Item? UpgradeItem(Scp914KnobSetting setting, Player player, Item item); - - /// - /// Called for each pickup in the intake chamber if the allows so. - /// - /// The used for this upgrade. - /// The to upgrade. - /// The position to teleport the upgraded pickups to. - /// The upgraded or null if it was destroyed. - /// - /// Use to remove pickups and to add pickups. - /// You can create more than one pickup during a single upgrade similar to items. - /// - public Pickup? UpgradePickup(Scp914KnobSetting setting, Pickup pickup, Vector3 newPosition); -} diff --git a/LabApi/Features/Wrappers/Facility/Rooms/Scp914/ItemProcessorAdapter.cs b/LabApi/Features/Wrappers/Facility/Rooms/Scp914/ItemProcessorAdapter.cs index 8a127b83..ad502299 100644 --- a/LabApi/Features/Wrappers/Facility/Rooms/Scp914/ItemProcessorAdapter.cs +++ b/LabApi/Features/Wrappers/Facility/Rooms/Scp914/ItemProcessorAdapter.cs @@ -19,10 +19,15 @@ internal class ItemProcessorAdapter : Scp914ItemProcessor /// /// Used internally by the base game. /// + /// The setting to update the item. + /// The base game item instance. + /// The . public override Scp914Result UpgradeInventoryItem(Scp914KnobSetting setting, ItemBase item) { if (Processor.UsePickupMethodOnly) + { return base.UpgradeInventoryItem(setting, item); + } return Processor.UpgradeItem(setting, Item.Get(item)); } @@ -30,6 +35,9 @@ public override Scp914Result UpgradeInventoryItem(Scp914KnobSetting setting, Ite /// /// Used internally by the base game. /// + /// The setting to update the item. + /// The base game pickup instance. + /// The . public override Scp914Result UpgradePickup(Scp914KnobSetting setting, ItemPickupBase pickup) => Processor.UpgradePickup(setting, Pickup.Get(pickup)); } diff --git a/LabApi/Features/Wrappers/Facility/Rooms/Scp914/Scp914.cs b/LabApi/Features/Wrappers/Facility/Rooms/Scp914/Scp914.cs index 8bef23d2..f7f610da 100644 --- a/LabApi/Features/Wrappers/Facility/Rooms/Scp914/Scp914.cs +++ b/LabApi/Features/Wrappers/Facility/Rooms/Scp914/Scp914.cs @@ -20,54 +20,14 @@ public class Scp914 : Room /// Gets the current instance. ///
/// - /// May be null if the map has not been generated yet or was previously destroyed. + /// May be if the map has not been generated yet or was previously destroyed. /// public static Scp914? Instance { get; private set; } /// - /// Contains all instances, accessible by their . + /// Contains all instances, accessible by their . /// - public static Dictionary ItemProcessorCache = []; - - /// - /// An internal constructor to prevent external instantiation. - /// - /// The room identifier for the pocket dimension. - internal Scp914(RoomIdentifier roomIdentifier) - : base(roomIdentifier) - { - if (CanCache) - Instance = this; - } - - /// - /// An internal method to set the instance to null when the base object is destroyed. - /// - internal override void OnRemoved() - { - base.OnRemoved(); - Instance = null; - } - - /// - /// Gets the main of the SCP-914 room. - /// - public Gate Gate => (Gate)Doors.FirstOrDefault(x => x is Gate); - - /// - /// Gets the entrance of the SCP-914 room. - /// - public Door Entrance => Doors.FirstOrDefault(x => x.Rooms.Length == 2); - - /// - /// Gets the intake of the SCP-914 machine. - /// - public Door IntakeDoor => Door.Get(Scp914Controller.Singleton.Doors.Last()); - - /// - /// Gets the output of the SCP-914 machine. - /// - public Door OutputDoor => Door.Get(Scp914Controller.Singleton.Doors.First()); + public static Dictionary ItemProcessorCache { get; } = []; /// /// Gets or sets the of the SCP-914 machine. @@ -87,10 +47,14 @@ public static bool IsUpgrading set { if (Scp914Controller.Singleton.IsUpgrading == value) + { return; + } if (value) + { Scp914Controller.Singleton.Upgrade(); + } else { Scp914Controller.Singleton.IsUpgrading = value; @@ -195,14 +159,14 @@ public static float DoorOpenDelay /// Interact with the SCP-914 machine. /// /// The type of interaction. - /// The that triggered the interaction or null if not specified. + /// The that triggered the interaction or if not specified. /// /// Interacting will also trigger SCP-914 related events. /// If you would not like to trigger events use and instead. /// public static void Interact(Scp914InteractCode interactCode, Player? player = null) { - player ??= Server.Host; + player ??= Server.Host!; Scp914Controller.Singleton.ServerInteract(player.ReferenceHub, (byte)interactCode); } @@ -218,25 +182,35 @@ public static void PlaySound(Scp914Sound sound) /// Gets the for the specified type. ///
/// The to get the associated . - /// The associated for the if found, otherwise null. + /// The associated for the if found, otherwise . /// /// If the item processor is a base game , will be a . /// public static IScp914ItemProcessor? GetItemProcessor(ItemType type) { if (!InventoryItemLoader.TryGetItem(type, out ItemBase item)) + { return null; + } if (ItemProcessorCache.TryGetValue(item, out var processor)) + { return processor; + } if (!item.TryGetComponent(out Scp914ItemProcessor baseProcessor)) + { return null; + } if (baseProcessor is ItemProcessorAdapter adaptor) + { ItemProcessorCache[item] = adaptor.Processor; + } else + { ItemProcessorCache[item] = new BaseGameItemProcessor(baseProcessor); + } return ItemProcessorCache[item]; } @@ -254,7 +228,9 @@ public static void PlaySound(Scp914Sound sound) foreach (ItemType type in Enum.GetValues(typeof(ItemType))) { if (!InventoryItemLoader.TryGetItem(type, out ItemBase _)) + { continue; + } result.Add(type, GetItemProcessor(type)); } @@ -268,13 +244,18 @@ public static void PlaySound(Scp914Sound sound) /// The class type that implements the interface. /// The to set the processor to. /// An instance of the processor. - public static void SetItemProcessor(ItemType type, T processor) where T : class, IScp914ItemProcessor + public static void SetItemProcessor(ItemType type, T processor) + where T : class, IScp914ItemProcessor { if (!InventoryItemLoader.TryGetItem(type, out ItemBase item)) + { return; + } if (item.TryGetComponent(out Scp914ItemProcessor baseProcessor)) + { UnityEngine.Object.Destroy(baseProcessor); + } item.gameObject.AddComponent().Processor = processor; ItemProcessorCache[item] = processor; @@ -286,12 +267,15 @@ public static void SetItemProcessor(ItemType type, T processor) where T : cla /// The class type that implements the interface. /// A predicate to match which Item Types to set the processor on using as a wrapper. /// An instance of the processor. - public static void SetItemProcessor(Func predicate, T processor) where T : class, IScp914ItemProcessor + public static void SetItemProcessor(Func predicate, T processor) + where T : class, IScp914ItemProcessor { - foreach(ItemType type in Enum.GetValues(typeof(ItemType))) + foreach (ItemType type in Enum.GetValues(typeof(ItemType))) { if (!InventoryItemLoader.TryGetItem(type, out ItemBase item) || !predicate(Item.Get(item))) + { continue; + } SetItemProcessor(type, processor); } @@ -305,14 +289,19 @@ public static void SetItemProcessor(Func predicate, T processor) /// /// Note that this is for setting the base game for an item, you should always use instead unless using already existing code see . /// - public static void SetItemProcessor(ItemType type) where T : Scp914ItemProcessor, new() + public static void SetItemProcessor(ItemType type) + where T : Scp914ItemProcessor, new() { if (!InventoryItemLoader.TryGetItem(type, out ItemBase item)) + { return; + } ItemProcessorCache.Remove(item); if (item.TryGetComponent(out Scp914ItemProcessor baseProcessor)) + { UnityEngine.Object.Destroy(baseProcessor); + } item.gameObject.AddComponent(); } @@ -325,14 +314,59 @@ public static void SetItemProcessor(Func predicate, T processor) /// /// Note that this is for setting the base game for an item, you should always use instead unless using already existing code. /// - public static void SetItemProcessor(Func predicate) where T : Scp914ItemProcessor, new() + public static void SetItemProcessor(Func predicate) + where T : Scp914ItemProcessor, new() { foreach (ItemType type in Enum.GetValues(typeof(ItemType))) { if (!InventoryItemLoader.TryGetItem(type, out ItemBase item) || !predicate(Item.Get(item))) + { continue; + } SetItemProcessor(type); } } + + /// + /// An internal constructor to prevent external instantiation. + /// + /// The room identifier for the pocket dimension. + internal Scp914(RoomIdentifier roomIdentifier) + : base(roomIdentifier) + { + if (CanCache) + { + Instance = this; + } + } + + /// + /// Gets the main of the SCP-914 room. + /// + public Gate Gate => (Gate)Doors.FirstOrDefault(x => x is Gate); + + /// + /// Gets the entrance of the SCP-914 room. + /// + public Door Entrance => Doors.FirstOrDefault(x => x.Rooms.Length == 2); + + /// + /// Gets the intake of the SCP-914 machine. + /// + public Door IntakeDoor => Door.Get(Scp914Controller.Singleton.Doors.Last()); + + /// + /// Gets the output of the SCP-914 machine. + /// + public Door OutputDoor => Door.Get(Scp914Controller.Singleton.Doors.First()); + + /// + /// An internal method to set the instance to null when the base object is destroyed. + /// + internal override void OnRemoved() + { + base.OnRemoved(); + Instance = null; + } } diff --git a/LabApi/Features/Wrappers/Facility/Round.cs b/LabApi/Features/Wrappers/Facility/Round.cs index 93855682..8a10c506 100644 --- a/LabApi/Features/Wrappers/Facility/Round.cs +++ b/LabApi/Features/Wrappers/Facility/Round.cs @@ -36,8 +36,10 @@ public static bool CanRoundEnd { get { - if (IsLocked || KeepRoundOnOne && ReferenceHub.AllHubs.Count(x => x.authManager.InstanceMode != ClientInstanceMode.DedicatedServer) < 2 || !IsRoundStarted) + if (IsLocked || (KeepRoundOnOne && (ReferenceHub.AllHubs.Count(x => x.authManager.InstanceMode != ClientInstanceMode.DedicatedServer) < 2)) || !IsRoundStarted) + { return false; + } return IsRoundStarted && !IsLocked; } @@ -133,7 +135,9 @@ public static int ExtraTargets public static void Restart(bool fastRestart = false, bool overrideRestartAction = false, NextRoundAction restartAction = NextRoundAction.DoNothing) { if (overrideRestartAction) + { StopNextRound = restartAction; + } bool prevValue = CustomNetworkManager.EnableFastRestart; CustomNetworkManager.EnableFastRestart = fastRestart; @@ -160,7 +164,9 @@ public static bool End(bool force = false) } if (!CanRoundEnd) + { return false; + } RoundSummary.singleton.ForceEnd(); return true; diff --git a/LabApi/Features/Wrappers/Facility/Structures/ExperimentalWeaponLocker.cs b/LabApi/Features/Wrappers/Facility/Structures/ExperimentalWeaponLocker.cs index c0f1425a..5806244a 100644 --- a/LabApi/Features/Wrappers/Facility/Structures/ExperimentalWeaponLocker.cs +++ b/LabApi/Features/Wrappers/Facility/Structures/ExperimentalWeaponLocker.cs @@ -1,9 +1,7 @@ using Interactables.Interobjects.DoorUtils; -using MapGeneration.Distributors; using System.Collections.Generic; using System.Diagnostics.CodeAnalysis; using System.Linq; -using System.Security; using BaseExperimentalWeaponLocker = MapGeneration.Distributors.ExperimentalWeaponLocker; namespace LabApi.Features.Wrappers; @@ -14,14 +12,30 @@ namespace LabApi.Features.Wrappers; public class ExperimentalWeaponLocker : Locker { /// - /// Contains all the cached experimental weapon lockers, accessible through their . + /// Contains all the cached experimental weapon lockers, accessible through their . /// - public new static Dictionary Dictionary { get; } = []; + public static new Dictionary Dictionary { get; } = []; /// /// A reference to all instances. /// - public new static IReadOnlyCollection List => Dictionary.Values; + public static new IReadOnlyCollection List => Dictionary.Values; + + /// + /// Gets the experimental weapon locker wrapper from the , or creates a new one if it doesn't exist and the provided was not . + /// + /// The of the experimental weapon locker. + /// The requested wrapper or . + [return: NotNullIfNotNull(nameof(baseLocker))] + public static ExperimentalWeaponLocker? Get(BaseExperimentalWeaponLocker? baseLocker) + { + if (baseLocker == null) + { + return null; + } + + return Dictionary.TryGetValue(baseLocker, out ExperimentalWeaponLocker found) ? found : (ExperimentalWeaponLocker)CreateStructureWrapper(baseLocker); + } /// /// An internal constructor to prevent external instantiation. @@ -31,16 +45,11 @@ internal ExperimentalWeaponLocker(BaseExperimentalWeaponLocker baseExperimentalW : base(baseExperimentalWeaponLocker) { Base = baseExperimentalWeaponLocker; - Dictionary.Add(baseExperimentalWeaponLocker, this); - } - /// - /// An internal method to remove itself from the cache when the abase object is destroyed. - /// - internal override void OnRemove() - { - base.OnRemove(); - Dictionary.Remove(Base); + if (CanCache) + { + Dictionary.Add(baseExperimentalWeaponLocker, this); + } } /// @@ -139,16 +148,11 @@ public ItemType[] AcceptableItems public void PlayDeniedSound(DoorPermissionFlags flags = DoorPermissionFlags.None) => Chamber.PlayDeniedSound(flags); /// - /// Gets the experimental weapon locker wrapper from the , or creates a new one if it doesn't exist and the provided was not . + /// An internal method to remove itself from the cache when the abase object is destroyed. /// - /// The of the experimental weapon locker. - /// The requested wrapper or . - [return: NotNullIfNotNull(nameof(baseLocker))] - public static ExperimentalWeaponLocker? Get(BaseExperimentalWeaponLocker? baseLocker) + internal override void OnRemove() { - if (baseLocker == null) - return null; - - return Dictionary.TryGetValue(baseLocker, out ExperimentalWeaponLocker found) ? found : (ExperimentalWeaponLocker)CreateStructureWrapper(baseLocker); + base.OnRemove(); + Dictionary.Remove(Base); } } diff --git a/LabApi/Features/Wrappers/Facility/Structures/Generator.cs b/LabApi/Features/Wrappers/Facility/Structures/Generator.cs index 017d68a4..3a762db3 100644 --- a/LabApi/Features/Wrappers/Facility/Structures/Generator.cs +++ b/LabApi/Features/Wrappers/Facility/Structures/Generator.cs @@ -1,10 +1,10 @@ -using Interactables.Interobjects.DoorUtils; +using Generators; +using Interactables.Interobjects.DoorUtils; +using MapGeneration; using MapGeneration.Distributors; using System.Collections.Generic; using System.Diagnostics.CodeAnalysis; using static MapGeneration.Distributors.Scp079Generator; -using Generators; -using MapGeneration; namespace LabApi.Features.Wrappers; @@ -16,31 +16,42 @@ public class Generator : Structure /// /// Contains all the cached generators in the game, accessible through their . /// - public new static Dictionary Dictionary { get; } = []; + public static new Dictionary Dictionary { get; } = []; /// - /// Contains generators in a list by room they are in. Generators that have been spawned without an assigned room are not inside of this collection. + /// A reference to all instances currently in the game. /// - private static Dictionary> GeneratorsByRoom { get; } = []; + public static new IReadOnlyCollection List => Dictionary.Values; /// - /// A reference to all instances currently in the game. + /// Contains generators in a list by room they are in. Generators that have been spawned without an assigned room are not inside of this collection. /// - public new static IReadOnlyCollection List => Dictionary.Values; + private static Dictionary> GeneratorsByRoom { get; } = []; /// - /// An internal constructor to prevent external instantiation. + /// Gets the generator wrapper from the , or creates a new one if it doesn't exist and the provided was not . /// - /// The of the generator. - internal Generator(Scp079Generator generator) - : base(generator) + /// The of the generator. + /// The requested wrapper or . + [return: NotNullIfNotNull(nameof(scp079Generator))] + public static Generator? Get(Scp079Generator? scp079Generator) { - Dictionary.Add(generator, this); - Base = generator; + if (scp079Generator == null) + { + return null; + } - TryRegisterByRoom(); + return Dictionary.TryGetValue(scp079Generator, out Generator generator) ? generator : (Generator)CreateStructureWrapper(scp079Generator); } + /// + /// Gets the generator wrapper from the or returns if specified room does not have any. + /// + /// Target room. + /// Generators found. + /// Whether the generator was found. + public static bool TryGetFromRoom(Room room, [NotNullWhen(true)] out List? generators) => GeneratorsByRoom.TryGetValue(room, out generators); + /// /// Initializes the generators by room caching for map generation. /// @@ -53,50 +64,25 @@ internal static void InitializeCaching() private static void SeedSynchronizer_OnGenerationFinished() { foreach (Generator generator in List) + { generator.TryRegisterByRoom(); + } } /// - /// An internal method remove itself from the cache when the base object is destroyed. + /// An internal constructor to prevent external instantiation. /// - internal override void OnRemove() + /// The of the generator. + internal Generator(Scp079Generator generator) + : base(generator) { - base.OnRemove(); - - if (Base.ParentRoom == null) - { - Dictionary.Remove(Base); - return; - } - - Room? room = Room.Get(Base.ParentRoom); - - if (room == null) // Room is null after round restart, try find it by iterating over the existing dictionary - { - Room? potentialRoom = null; - foreach (var kvp in GeneratorsByRoom) - { - if (kvp.Value.Contains(this)) - { - potentialRoom = kvp.Key; - break; - } - } - - room = potentialRoom; - } + Base = generator; - if (room != null && GeneratorsByRoom.TryGetValue(room, out List list)) + if (CanCache) { - list.Remove(this); - - if (list.Count == 0) - { - GeneratorsByRoom.Remove(room); - } + Dictionary.Add(generator, this); + TryRegisterByRoom(); } - - Dictionary.Remove(Base); } /// @@ -165,7 +151,7 @@ public bool IsUnlocked public float ActivationTime => Base.ActivationTime; /// - /// Gets or sets whether the generator is engaged. + /// Gets or sets whether the generator is engaged. /// public bool Engaged { @@ -198,55 +184,83 @@ public short RemainingTime /// The triggered. public void ServerInteract(Player player, GeneratorColliderId collider) => Base.ServerInteract(player.ReferenceHub, (byte)collider); + /// + /// Plays the denied sound cue on the client. + /// + /// The permissions used to attempt opening the generator. Used to animate the generator panel. + public void PlayerDeniedBeep(DoorPermissionFlags flags) => Base.RpcDenied(flags); + + /// + /// An internal method remove itself from the cache when the base object is destroyed. + /// + internal override void OnRemove() + { + base.OnRemove(); + + if (Base.ParentRoom == null) + { + Dictionary.Remove(Base); + return; + } + + Room? room = Room.Get(Base.ParentRoom); + + if (room == null) // Room is null after round restart, try find it by iterating over the existing dictionary + { + Room? potentialRoom = null; + foreach (var kvp in GeneratorsByRoom) + { + if (kvp.Value.Contains(this)) + { + potentialRoom = kvp.Key; + break; + } + } + + room = potentialRoom; + } + + if (room != null && GeneratorsByRoom.TryGetValue(room, out List list)) + { + list.Remove(this); + + if (list.Count == 0) + { + GeneratorsByRoom.Remove(room); + } + } + + Dictionary.Remove(Base); + } + private void TryRegisterByRoom() { foreach (var kvp in GeneratorsByRoom) { if (kvp.Value.Contains(this)) + { return; + } } if (Base.ParentRoom == null) + { return; + } + Room? room = Room.Get(Base.ParentRoom); if (room == null) + { return; + } if (!GeneratorsByRoom.TryGetValue(room, out List list)) { - list = new List(); + list = []; GeneratorsByRoom.Add(room, list); } list.Add(this); } - - /// - /// Plays the denied sound cue on the client. - /// - /// The permissions used to attempt opening the generator. Used to animate the generator panel. - public void PlayerDeniedBeep(DoorPermissionFlags flags) => Base.RpcDenied(flags); - - /// - /// Gets the generator wrapper from the , or creates a new one if it doesn't exist and the provided was not . - /// - /// The of the generator. - /// The requested wrapper or . - [return: NotNullIfNotNull(nameof(scp079Generator))] - public static Generator? Get(Scp079Generator? scp079Generator) - { - if (scp079Generator == null) - return null; - - return Dictionary.TryGetValue(scp079Generator, out Generator generator) ? generator : (Generator)CreateStructureWrapper(scp079Generator); - } - - /// - /// Gets the generator wrapper from the or returns if specified room does not have any. - /// - /// Target room. - /// Generators found. - /// Whether the generator was found. - public static bool TryGetFromRoom(Room room, [NotNullWhen(true)] out List? generators) => GeneratorsByRoom.TryGetValue(room, out generators); } \ No newline at end of file diff --git a/LabApi/Features/Wrappers/Facility/Structures/LargeLocker.cs b/LabApi/Features/Wrappers/Facility/Structures/LargeLocker.cs index ecd5e3db..c4d5cc4e 100644 --- a/LabApi/Features/Wrappers/Facility/Structures/LargeLocker.cs +++ b/LabApi/Features/Wrappers/Facility/Structures/LargeLocker.cs @@ -11,12 +11,12 @@ public class LargeLocker : Locker /// /// Contains all the cached large lockers, accessible through their . /// - public new static Dictionary Dictionary = []; + public static new Dictionary Dictionary { get; } = []; /// /// A reference to all instances. /// - public new static IReadOnlyCollection List => Dictionary.Values; + public static new IReadOnlyCollection List => Dictionary.Values; /// /// An internal constructor to prevent external instantiation. @@ -25,16 +25,10 @@ public class LargeLocker : Locker internal LargeLocker(BaseLocker baseLocker) : base(baseLocker) { - Dictionary.Add(baseLocker, this); - } - - /// - /// An internal method to remove itself from the cache when the base object is destroyed. - /// - internal override void OnRemove() - { - base.OnRemove(); - Dictionary.Remove(Base); + if (CanCache) + { + Dictionary.Add(baseLocker, this); + } } /// @@ -86,4 +80,13 @@ internal override void OnRemove() /// Gets the drawer chamber that is at the bottom. /// public LockerChamber Drawer => Chambers[9]; + + /// + /// An internal method to remove itself from the cache when the base object is destroyed. + /// + internal override void OnRemove() + { + base.OnRemove(); + Dictionary.Remove(Base); + } } diff --git a/LabApi/Features/Wrappers/Facility/Structures/Locker.cs b/LabApi/Features/Wrappers/Facility/Structures/Locker.cs index 8e584392..9633cf1d 100644 --- a/LabApi/Features/Wrappers/Facility/Structures/Locker.cs +++ b/LabApi/Features/Wrappers/Facility/Structures/Locker.cs @@ -1,5 +1,4 @@ -using InventorySystem.Items.MicroHID; -using MapGeneration.Distributors; +using MapGeneration.Distributors; using NorthwoodLib.Pools; using System.Collections.Generic; using System.Diagnostics.CodeAnalysis; @@ -17,35 +16,43 @@ public class Locker : Structure /// /// Contains all the cached lockers, accessible through their . /// - public new static Dictionary Dictionary { get; } = []; + public static new Dictionary Dictionary { get; } = []; /// /// A reference to all instances. /// - public new static IReadOnlyCollection List => Dictionary.Values; + public static new IReadOnlyCollection List => Dictionary.Values; /// - /// An internal constructor to prevent external instantiation. + /// Gets the locker wrapper from the , or creates a new one if it doesn't exist and the provided was not . /// - /// The base object. - internal Locker(BaseLocker baseLocker) - : base(baseLocker) + /// The of the locker. + /// The requested wrapper or . + [return: NotNullIfNotNull(nameof(baseLocker))] + public static Locker? Get(BaseLocker? baseLocker) { - Dictionary.Add(baseLocker, this); - Base = baseLocker; - Chambers = baseLocker.Chambers.Select(x => LockerChamber.Get(x)).ToArray(); + if (baseLocker == null) + { + return null; + } + + return Dictionary.TryGetValue(baseLocker, out Locker found) ? found : (Locker)CreateStructureWrapper(baseLocker); } /// - /// An internal method to remove itself from the cache when the base object is destroyed. + /// An internal constructor to prevent external instantiation. /// - internal override void OnRemove() + /// The base object. + internal Locker(BaseLocker baseLocker) + : base(baseLocker) { - base.OnRemove(); - Dictionary.Remove(Base); + Base = baseLocker; + Chambers = baseLocker.Chambers.Select(static x => LockerChamber.Get(x)).ToArray(); - foreach (LockerChamber chamber in Chambers) - chamber.OnRemove(); + if (CanCache) + { + Dictionary.Add(baseLocker, this); + } } /// @@ -101,7 +108,7 @@ public int MaxChambersToFill /// /// Adds a new entry to the possible spawnable . /// - /// The to spawn. might only support certain values see + /// The to spawn. might only support certain values see . /// The number of times this loot is selected to spawn in a chamber. /// The probability weight given for this loot to spawn over other instances. /// The minimum number of items to spawn per chamber. @@ -118,7 +125,7 @@ public void AddLockerLoot(ItemType type, int remainingUses, int probabilityPoint RemainingUses = remainingUses, ProbabilityPoints = probabilityPoints, MinPerChamber = minPerChamber, - MaxPerChamber= maxPerChamber + MaxPerChamber = maxPerChamber, }; Base.Loot = [.. Base.Loot, loot]; @@ -145,11 +152,15 @@ public void FillChambers() { int removeCount = Chambers.Count - Random.Range(MinChambersToFill, MaxChambersToFill + 1); for (int i = 0; i < removeCount; i++) + { chambers.RemoveAt(Random.Range(0, chambers.Count)); + } } foreach (LockerChamber chamber in chambers) + { chamber.Fill(); + } ListPool.Shared.Return(chambers); } @@ -163,7 +174,9 @@ public void FillChambers() public void FillAllChambers() { foreach (LockerChamber chamber in Chambers) + { chamber.Fill(); + } } /// @@ -172,7 +185,9 @@ public void FillAllChambers() public void ClearAllChambers() { foreach (LockerChamber chamber in Chambers) + { chamber.RemoveAllItems(); + } } /// @@ -181,7 +196,9 @@ public void ClearAllChambers() public void OpenAllChambers() { foreach (LockerChamber chamber in Chambers) + { chamber.IsOpen = true; + } } /// @@ -190,21 +207,22 @@ public void OpenAllChambers() public void CloseAllChambers() { foreach (LockerChamber chamber in Chambers) + { chamber.IsOpen = false; + } } /// - /// Gets the locker wrapper from the , or creates a new one if it doesn't exist and the provided was not . + /// An internal method to remove itself from the cache when the base object is destroyed. /// - /// The of the locker. - /// The requested wrapper or . - [return: NotNullIfNotNull(nameof(baseLocker))] - public static Locker? Get(BaseLocker? baseLocker) + internal override void OnRemove() { - if (baseLocker == null) - return null; + base.OnRemove(); + Dictionary.Remove(Base); - return Dictionary.TryGetValue(baseLocker, out Locker found) ? found : (Locker)CreateStructureWrapper(baseLocker); + foreach (LockerChamber chamber in Chambers) + { + chamber.OnRemove(); + } } } - diff --git a/LabApi/Features/Wrappers/Facility/Structures/LockerChamber.cs b/LabApi/Features/Wrappers/Facility/Structures/LockerChamber.cs index 13aa667e..bd6bb558 100644 --- a/LabApi/Features/Wrappers/Facility/Structures/LockerChamber.cs +++ b/LabApi/Features/Wrappers/Facility/Structures/LockerChamber.cs @@ -6,8 +6,8 @@ using System.Diagnostics.CodeAnalysis; using System.Linq; using UnityEngine; -using BaseLockerChamber = MapGeneration.Distributors.LockerChamber; using BaseLocker = MapGeneration.Distributors.Locker; +using BaseLockerChamber = MapGeneration.Distributors.LockerChamber; namespace LabApi.Features.Wrappers; @@ -21,6 +21,28 @@ public class LockerChamber /// public static Dictionary Dictionary { get; } = []; + /// + /// Gets the locker chamber wrapper from the or creates a new if it doesn't exist and the provided was not null. + /// + /// The object. + /// The requested locker chamber wrapper or null. + [return: NotNullIfNotNull(nameof(baseLockerChamber))] + public static LockerChamber? Get(BaseLockerChamber? baseLockerChamber) + { + if (baseLockerChamber == null) + { + return null; + } + + return Dictionary.TryGetValue(baseLockerChamber, out LockerChamber lockerChamber) ? lockerChamber : CreateLockerChamberWrapper(baseLockerChamber); + } + + private static LockerChamber CreateLockerChamberWrapper(BaseLockerChamber baseLockerChamber) + { + BaseLocker locker = baseLockerChamber.GetComponentInParent(); + return new LockerChamber(baseLockerChamber, (Locker)Structure.Get(locker), (byte)locker.Chambers.IndexOf(baseLockerChamber)); + } + /// /// An internal constructor to prevent external instantiation. /// @@ -29,18 +51,14 @@ public class LockerChamber /// The id of the chamber inside the locker. internal LockerChamber(BaseLockerChamber baseLockerChamber, Locker locker, byte id) { - Dictionary.Add(baseLockerChamber, this); Base = baseLockerChamber; Locker = locker; Id = id; - } - /// - /// An internal method to remove itself from the cache when the base object is destroyed. - /// - internal void OnRemove() - { - Dictionary.Remove(Base); + if (locker.CanCache) + { + Dictionary.Add(baseLockerChamber, this); + } } /// @@ -128,7 +146,9 @@ public void Fill() foreach (ItemPickupBase pickupBase in Base.Content) { if (!pickupBase.TryGetComponent(out Rigidbody rigidbody)) + { continue; + } rigidbody.isKinematic = false; } @@ -161,7 +181,9 @@ public HashSet GetAllItems() public void RemoveAllItems() { foreach (ItemPickupBase pickupBase in Base.Content) + { pickupBase.DestroySelf(); + } Base.Content.Clear(); Base.ToBeSpawned.Clear(); @@ -185,7 +207,7 @@ public void RemoveItem(Pickup pickup) /// The created . public Pickup AddItem(ItemType type) { - Pickup pickup = Pickup.Create(type, Base.Spawnpoint.position, Base.Spawnpoint.rotation); + Pickup pickup = Pickup.Create(type, Base.Spawnpoint.position, Base.Spawnpoint.rotation)!; pickup.Transform.SetParent(Base.Spawnpoint); Base.Content.Add(pickup.Base); (pickup.Base as IPickupDistributorTrigger)?.OnDistributed(); @@ -196,9 +218,13 @@ public Pickup AddItem(ItemType type) } if (Base.SpawnOnFirstChamberOpening && !IsOpen) + { Base.ToBeSpawned.Add(pickup.Base); + } else + { pickup.Spawn(); + } return pickup; } @@ -213,7 +239,9 @@ public Pickup AddItem(ItemType type) public void Interact(Player player) { if (player == null) + { throw new ArgumentNullException(nameof(player)); + } Locker.Base.ServerInteract(player.ReferenceHub, Id); } @@ -225,22 +253,10 @@ public void Interact(Player player) public void PlayDeniedSound(DoorPermissionFlags permissionUsed) => Locker.Base.RpcPlayDenied(Id, permissionUsed); /// - /// Gets the locker chamber wrapper from the or creates a new if it doesn't exist and the provided was not null. + /// An internal method to remove itself from the cache when the base object is destroyed. /// - /// The object. - /// The requested locker chamber wrapper or null. - [return: NotNullIfNotNull(nameof(baseLockerChamber))] - public static LockerChamber? Get(BaseLockerChamber? baseLockerChamber) - { - if (baseLockerChamber == null) - return null; - - return Dictionary.TryGetValue(baseLockerChamber, out LockerChamber lockerChamber) ? lockerChamber : CreateLockerChamberWrapper(baseLockerChamber); - } - - private static LockerChamber CreateLockerChamberWrapper(BaseLockerChamber baseLockerChamber) + internal void OnRemove() { - BaseLocker locker = baseLockerChamber.GetComponentInParent(); - return new LockerChamber(baseLockerChamber, (Locker)Structure.Get(locker), (byte)locker.Chambers.IndexOf(baseLockerChamber)); + Dictionary.Remove(Base); } } \ No newline at end of file diff --git a/LabApi/Features/Wrappers/Facility/Structures/MicroPedestal.cs b/LabApi/Features/Wrappers/Facility/Structures/MicroPedestal.cs index 46ea3352..00f5377c 100644 --- a/LabApi/Features/Wrappers/Facility/Structures/MicroPedestal.cs +++ b/LabApi/Features/Wrappers/Facility/Structures/MicroPedestal.cs @@ -12,21 +12,42 @@ public class MicroPedestal : Locker /// /// Contains all the micro pedestals, accessible through their . /// - public new static Dictionary Dictionary { get; } = []; + public static new Dictionary Dictionary { get; } = []; /// /// A reference to all instances. /// - public new static IReadOnlyCollection List => Dictionary.Values; + public static new IReadOnlyCollection List => Dictionary.Values; + + /// + /// Gets the micro pedestal wrapper from the , or creates a new one if it doesn't exist and the provided was not . + /// + /// The of the experimental weapon locker. + /// The requested wrapper or . + [return: NotNullIfNotNull(nameof(basePedestal))] + public static MicroPedestal? Get(MicroHIDPedestal? basePedestal) + { + if (basePedestal == null) + { + return null; + } + + return Dictionary.TryGetValue(basePedestal, out MicroPedestal found) ? found : (MicroPedestal)CreateStructureWrapper(basePedestal); + } /// /// An internal constructor to prevent external instantiation. /// /// The base object. - internal MicroPedestal(MicroHIDPedestal pedestal) : base(pedestal) + internal MicroPedestal(MicroHIDPedestal pedestal) + : base(pedestal) { - Dictionary.Add(pedestal, this); Base = pedestal; + + if (CanCache) + { + Dictionary.Add(pedestal, this); + } } /// @@ -42,18 +63,4 @@ internal override void OnRemove() base.OnRemove(); Dictionary.Remove(Base); } - - /// - /// Gets the micro pedestal wrapper from the , or creates a new one if it doesn't exist and the provided was not . - /// - /// The of the experimental weapon locker. - /// The requested wrapper or . - [return: NotNullIfNotNull(nameof(basePedestal))] - public static MicroPedestal? Get(MicroHIDPedestal? basePedestal) - { - if (basePedestal == null) - return null; - - return Dictionary.TryGetValue(basePedestal, out MicroPedestal found) ? found : (MicroPedestal)CreateStructureWrapper(basePedestal); - } } diff --git a/LabApi/Features/Wrappers/Facility/Structures/PedestalLocker.cs b/LabApi/Features/Wrappers/Facility/Structures/PedestalLocker.cs index af416467..31955cdb 100644 --- a/LabApi/Features/Wrappers/Facility/Structures/PedestalLocker.cs +++ b/LabApi/Features/Wrappers/Facility/Structures/PedestalLocker.cs @@ -1,5 +1,4 @@ using Interactables.Interobjects.DoorUtils; -using InventorySystem.Items.MicroHID; using MapGeneration.Distributors; using System.Collections.Generic; using System.Diagnostics.CodeAnalysis; @@ -15,12 +14,28 @@ public class PedestalLocker : Locker /// /// Contains all the cached pedestal lockers, accessible through their . /// - public new static Dictionary Dictionary { get; } = []; + public static new Dictionary Dictionary { get; } = []; /// /// A reference to all instances. /// - public new static IReadOnlyCollection List => Dictionary.Values; + public static new IReadOnlyCollection List => Dictionary.Values; + + /// + /// Gets the pedestal wrapper from the , or creates a new one if it doesn't exist and the provided was not . + /// + /// The of the pedestal locker. + /// The requested wrapper or . + [return: NotNullIfNotNull(nameof(basePedestal))] + public static PedestalLocker? Get(PedestalScpLocker? basePedestal) + { + if (basePedestal == null) + { + return null; + } + + return Dictionary.TryGetValue(basePedestal, out PedestalLocker found) ? found : (PedestalLocker)CreateStructureWrapper(basePedestal); + } /// /// An internal constructor to prevent external instantiation. @@ -30,16 +45,11 @@ internal PedestalLocker(PedestalScpLocker pedestalScpLocker) : base(pedestalScpLocker) { Base = pedestalScpLocker; - Dictionary.Add(pedestalScpLocker, this); - } - /// - /// An internal method to remove itself from the cache when the base object is destroyed. - /// - internal override void OnRemove() - { - base.OnRemove(); - Dictionary.Remove(Base); + if (CanCache) + { + Dictionary.Add(pedestalScpLocker, this); + } } /// @@ -138,16 +148,11 @@ public ItemType[] AcceptableItems public void PlayDeniedSound(DoorPermissionFlags flags = DoorPermissionFlags.None) => Chamber.PlayDeniedSound(flags); /// - /// Gets the pedestal wrapper from the , or creates a new one if it doesn't exist and the provided was not . + /// An internal method to remove itself from the cache when the base object is destroyed. /// - /// The of the pedestal locker. - /// The requested wrapper or . - [return: NotNullIfNotNull(nameof(basePedestal))] - public static PedestalLocker? Get(PedestalScpLocker? basePedestal) + internal override void OnRemove() { - if (basePedestal == null) - return null; - - return Dictionary.TryGetValue(basePedestal, out PedestalLocker found) ? found : (PedestalLocker)CreateStructureWrapper(basePedestal); + base.OnRemove(); + Dictionary.Remove(Base); } } diff --git a/LabApi/Features/Wrappers/Facility/Structures/RifleRackLocker.cs b/LabApi/Features/Wrappers/Facility/Structures/RifleRackLocker.cs index faa743d9..5f4a7bc5 100644 --- a/LabApi/Features/Wrappers/Facility/Structures/RifleRackLocker.cs +++ b/LabApi/Features/Wrappers/Facility/Structures/RifleRackLocker.cs @@ -12,30 +12,24 @@ public class RifleRackLocker : Locker /// /// Contains all the cached rifle rack lockers, accessible through their . /// - public new static Dictionary Dictionary { get; } = []; + public static new Dictionary Dictionary { get; } = []; /// /// A reference to all instances. /// - public new static IReadOnlyCollection List => Dictionary.Values; + public static new IReadOnlyCollection List => Dictionary.Values; /// /// An internal constructor to prevent external instantiation. /// /// The base object. internal RifleRackLocker(BaseLocker baseLocker) - :base(baseLocker) + : base(baseLocker) { - Dictionary.Add(baseLocker, this); - } - - /// - /// An internal method to remove itself from the cache when the base object is destroyed. - /// - internal override void OnRemove() - { - base.OnRemove(); - Dictionary.Remove(Base); + if (CanCache) + { + Dictionary.Add(baseLocker, this); + } } /// @@ -46,7 +40,7 @@ public bool IsOpen get => MainChamber.IsOpen; set => MainChamber.IsOpen = value; } - + /// /// Gets whether the rifle rack can be interacted with by a . /// @@ -110,4 +104,13 @@ public float TargetCooldown /// Gets the chamber used for grenade spawn 2. /// public LockerChamber HeGrenade2 => Chambers[6]; + + /// + /// An internal method to remove itself from the cache when the base object is destroyed. + /// + internal override void OnRemove() + { + base.OnRemove(); + Dictionary.Remove(Base); + } } diff --git a/LabApi/Features/Wrappers/Facility/Structures/StandardLocker.cs b/LabApi/Features/Wrappers/Facility/Structures/StandardLocker.cs index b8ada6fc..79b4e76d 100644 --- a/LabApi/Features/Wrappers/Facility/Structures/StandardLocker.cs +++ b/LabApi/Features/Wrappers/Facility/Structures/StandardLocker.cs @@ -11,12 +11,12 @@ public class StandardLocker : Locker /// /// Contains all the cached standard lockers, accessible through their . /// - public new static Dictionary Dictionary { get; } = []; + public static new Dictionary Dictionary { get; } = []; /// /// A reference to all instances. /// - public new static IReadOnlyCollection List => Dictionary.Values; + public static new IReadOnlyCollection List => Dictionary.Values; /// /// An internal constructor to prevent external instantiation. @@ -25,16 +25,10 @@ public class StandardLocker : Locker internal StandardLocker(BaseLocker baseLocker) : base(baseLocker) { - Dictionary.Add(baseLocker, this); - } - - /// - /// An internal method to remove itself from the cache when the abase object is destroyed. - /// - internal override void OnRemove() - { - base.OnRemove(); - Dictionary.Remove(Base); + if (CanCache) + { + Dictionary.Add(baseLocker, this); + } } /// @@ -84,4 +78,13 @@ internal override void OnRemove() /// This chamber does not control any doors. /// public LockerChamber BottomRight => Chambers[3]; + + /// + /// An internal method to remove itself from the cache when the abase object is destroyed. + /// + internal override void OnRemove() + { + base.OnRemove(); + Dictionary.Remove(Base); + } } diff --git a/LabApi/Features/Wrappers/Facility/Structures/Structure.cs b/LabApi/Features/Wrappers/Facility/Structures/Structure.cs index 69b9b543..b1da20ce 100644 --- a/LabApi/Features/Wrappers/Facility/Structures/Structure.cs +++ b/LabApi/Features/Wrappers/Facility/Structures/Structure.cs @@ -15,6 +15,49 @@ namespace LabApi.Features.Wrappers; /// public class Structure { + /// + /// Contains all the handlers for constructing wrappers for the associated base game types. + /// + private static readonly Dictionary> TypeWrappers = []; + + /// + /// Contains all the cached structures, accessible through their . + /// + public static Dictionary Dictionary { get; } = []; + + /// + /// A reference to all instances. + /// + public static IReadOnlyCollection List => Dictionary.Values; + + /// + /// Gets the structure wrapper from the or creates a new one if it doesn't exist and the provided was not null. + /// + /// The of the structure. + /// The requested structure or null. + [return: NotNullIfNotNull(nameof(spawnableStructure))] + public static Structure? Get(SpawnableStructure? spawnableStructure) + { + if (spawnableStructure == null) + { + return null; + } + + return Dictionary.TryGetValue(spawnableStructure, out Structure structure) ? structure : CreateStructureWrapper(spawnableStructure); + } + + /// + /// Tries to get the structure wrapper from the . + /// + /// The of the structure. + /// The requested structure. + /// True of the structure exists, otherwise false. + public static bool TryGet(SpawnableStructure? spawnableStructure, [NotNullWhen(true)] out Structure? structure) + { + structure = Get(spawnableStructure); + return structure != null; + } + /// /// Initializes the wrapper by subscribing to events. /// @@ -42,19 +85,65 @@ internal static void Initialize() } /// - /// Contains all the handlers for constructing wrappers for the associated base game types. + /// Creates a new wrapper from the base game object. /// - private static readonly Dictionary> typeWrappers = []; + /// The base game structure to wrap. + /// The newly created wrapper. + protected static Structure CreateStructureWrapper(SpawnableStructure structure) + { + Type targetType = structure.GetType(); + if (!TypeWrappers.TryGetValue(targetType, out Func handler)) + { +#if DEBUG + Logger.Warn($"Unable to find {nameof(Structure)} wrapper for {targetType.Name}, backup up to base constructor!"); +#endif + return new Structure(structure); + } + + Structure? wrapper = handler?.Invoke(structure); + if (wrapper == null) + { + Logger.Error($"Failed to create structure wrapper. A handler returned null for type {structure.GetType()}"); + return null!; + } + + return wrapper!; + } /// - /// Contains all the cached structures, accessible through their . + /// Private method to handle the creation of new structures in the server. /// - public static Dictionary Dictionary { get; } = []; + /// The that was created. + private static void OnAdded(SpawnableStructure structure) + { + if (!Dictionary.ContainsKey(structure)) + { + _ = CreateStructureWrapper(structure); + } + } /// - /// A reference to all instances. + /// Private method to handle the removal of structures from the server. /// - public static IReadOnlyCollection List => Dictionary.Values; + /// The that was removed. + private static void OnRemoved(SpawnableStructure spawnableStructure) + { + if (Dictionary.TryGetValue(spawnableStructure, out Structure structure)) + { + structure.OnRemove(); + } + } + + /// + /// A private method to handle the addition of wrapper handlers. + /// + /// The derived base game type to handle. + /// A handler to construct the wrapper with the base game instance. + private static void Register(Func constructor) + where T : SpawnableStructure + { + TypeWrappers.Add(typeof(T), x => constructor((T)x)); + } /// /// An internal constructor to prevent external instantiation. @@ -62,17 +151,13 @@ internal static void Initialize() /// The base object. internal Structure(SpawnableStructure spawnableStructure) { - Dictionary.Add(spawnableStructure, this); Base = spawnableStructure; StructurePositionSync = Base.gameObject.GetComponent(); - } - /// - /// An internal method to remove itself from the cache when the base object is destroyed. - /// - internal virtual void OnRemove() - { - Dictionary.Remove(Base); + if (CanCache) + { + Dictionary.Add(spawnableStructure, this); + } } /// @@ -137,6 +222,11 @@ public float RotationY /// public Room? Room => Room.Get(Base.ParentRoom); + /// + /// Whether to cache the wrapper. + /// + protected internal bool CanCache => !IsDestroyed && Base.isActiveAndEnabled; + // TODO: implement structure spawning. /// @@ -162,84 +252,10 @@ public override string ToString() } /// - /// Gets the structure wrapper from the or creates a new one if it doesn't exist and the provided was not null. - /// - /// The of the structure. - /// The requested structure or null. - [return: NotNullIfNotNull(nameof(spawnableStructure))] - public static Structure? Get(SpawnableStructure? spawnableStructure) - { - if (spawnableStructure == null) - return null; - - return Dictionary.TryGetValue(spawnableStructure, out Structure structure) ? structure : CreateStructureWrapper(spawnableStructure); - } - - /// - /// Tries to get the structure wrapper from the . - /// - /// The of the structure. - /// The requested structure. - /// True of the structure exists, otherwise false. - public static bool TryGet(SpawnableStructure? spawnableStructure, [NotNullWhen(true)] out Structure? structure) - { - structure = Get(spawnableStructure); - return structure != null; - } - - /// - /// Creates a new wrapper from the base game object. - /// - /// The base game structure to wrap. - /// The newly created wrapper. - protected static Structure CreateStructureWrapper(SpawnableStructure structure) - { - Type targetType = structure.GetType(); - if (!typeWrappers.TryGetValue(targetType, out Func handler)) - { -#if DEBUG - Logger.Warn($"Unable to find {nameof(Structure)} wrapper for {targetType.Name}, backup up to base constructor!"); -#endif - return new Structure(structure); - } - - Structure? wrapper = handler?.Invoke(structure); - if (wrapper == null) - { - Logger.Error($"Failed to create structure wrapper. A handler returned null for type {structure.GetType()}"); - return null; - } - - return wrapper!; - } - - /// - /// Private method to handle the creation of new structures in the server. - /// - /// The that was created. - private static void OnAdded(SpawnableStructure structure) - { - if (!Dictionary.ContainsKey(structure)) - _ = CreateStructureWrapper(structure); - } - - /// - /// Private method to handle the removal of structures from the server. - /// - /// The that was removed. - private static void OnRemoved(SpawnableStructure spawnableStructure) - { - if (Dictionary.TryGetValue(spawnableStructure, out Structure structure)) - structure.OnRemove(); - } - - /// - /// A private method to handle the addition of wrapper handlers. + /// An internal method to remove itself from the cache when the base object is destroyed. /// - /// The derived base game type to handle. - /// A handler to construct the wrapper with the base game instance. - private static void Register(Func constructor) where T : SpawnableStructure + internal virtual void OnRemove() { - typeWrappers.Add(typeof(T), x => constructor((T)x)); + Dictionary.Remove(Base); } } diff --git a/LabApi/Features/Wrappers/Facility/Structures/WallCabinet.cs b/LabApi/Features/Wrappers/Facility/Structures/WallCabinet.cs index f22ab7e6..4f5efd98 100644 --- a/LabApi/Features/Wrappers/Facility/Structures/WallCabinet.cs +++ b/LabApi/Features/Wrappers/Facility/Structures/WallCabinet.cs @@ -12,12 +12,12 @@ public class WallCabinet : Locker /// /// Contains all the cached wall cabinets, accessible through their . /// - public new static Dictionary Dictionary { get; } = []; + public static new Dictionary Dictionary { get; } = []; /// /// A reference to all instances. /// - public new static IReadOnlyCollection List => Dictionary.Values; + public static new IReadOnlyCollection List => Dictionary.Values; /// /// An internal constructor to prevent external instantiation. @@ -26,16 +26,10 @@ public class WallCabinet : Locker internal WallCabinet(BaseLocker baseLocker) : base(baseLocker) { - Dictionary.Add(baseLocker, this); - } - - /// - /// An internal method to remove itself form the cache when the base object is destroyed. - /// - internal override void OnRemove() - { - base.OnRemove(); - Dictionary.Remove(Base); + if (CanCache) + { + Dictionary.Add(baseLocker, this); + } } /// @@ -96,4 +90,13 @@ public float TargetCooldown /// This chamber does not control any doors. /// public LockerChamber UpperShelf => Chambers[2]; + + /// + /// An internal method to remove itself form the cache when the base object is destroyed. + /// + internal override void OnRemove() + { + base.OnRemove(); + Dictionary.Remove(Base); + } } diff --git a/LabApi/Features/Wrappers/Facility/Structures/Window.cs b/LabApi/Features/Wrappers/Facility/Structures/Window.cs new file mode 100644 index 00000000..7ca44b49 --- /dev/null +++ b/LabApi/Features/Wrappers/Facility/Structures/Window.cs @@ -0,0 +1,164 @@ +using Generators; +using MapGeneration.Distributors; +using PlayerStatsSystem; +using System.Collections.Generic; +using System.Diagnostics.CodeAnalysis; +using UnityEngine; + +namespace LabApi.Features.Wrappers; + +/// +/// The wrapper over the object. +/// +public class Window +{ + /// + /// Initializes the wrapper by subscribing to events. + /// + [InitializeWrapper] + internal static void Initialize() + { + BreakableWindow.OnAdded += OnAdded; + BreakableWindow.OnDestroyed += OnRemoved; + } + + /// + /// Contains all the cached structures, accessible through their . + /// + public static Dictionary Dictionary { get; } = []; + + /// + /// A reference to all instances. + /// + public static IReadOnlyCollection List => Dictionary.Values; + + /// + /// An internal constructor to prevent external instantiation. + /// + /// The base object. + internal Window(BreakableWindow breakableWindow) + { + Base = breakableWindow; + + if (CanCache) + Dictionary.Add(breakableWindow, this); + } + + /// + /// An internal method to remove itself from the cache when the base object is destroyed. + /// + internal virtual void OnRemove() + { + Dictionary.Remove(Base); + } + + /// + /// The base object. + /// + public BreakableWindow Base { get; } + + /// + /// Gets the structure's . + /// + public GameObject GameObject => Base.gameObject; + + /// + /// Gets the structure's . + /// + public Transform Transform => Base.transform; + + /// + /// Whether to cache the wrapper. + /// + protected internal bool CanCache => !IsDestroyed && Base.isActiveAndEnabled; + + /// + /// Gets whether the window gameobject was destroyed. + /// + public bool IsDestroyed => Base == null || GameObject == null; + + /// + /// Gets whether the window is broken. + /// + public bool IsBroken => Base.NetworkIsBroken; + + /// + /// Gets or sets window's health. + /// + public float Health + { + get => Base.Health; + set + { + Base.Damage(Base.Health - value, new CustomReasonDamageHandler(string.Empty), Vector3.zero); + } + } + + /// + /// Gets the window's position. + /// + public Vector3 Position + { + get => Transform.position; + } + + /// + /// Gets the window's rotation. + /// + public Quaternion Rotation + { + get => Transform.rotation; + } + + /// + public override string ToString() + { + return $"[{GetType().Name}: Position={Position}, Rotation={Rotation} IsDestroyed={IsDestroyed}]"; + } + + /// + /// Gets the structure wrapper from the or creates a new one if it doesn't exist and the provided was not . + /// + /// The of the window. + /// The requested structure or . + [return: NotNullIfNotNull(nameof(breakableWindow))] + public static Window? Get(BreakableWindow? breakableWindow) + { + if (breakableWindow == null) + return null; + + return Dictionary.TryGetValue(breakableWindow, out Window structure) ? structure : new Window(breakableWindow); + } + + /// + /// Tries to get the window wrapper from the . + /// + /// The of the window. + /// The requested window. + /// of the structure exists, otherwise . + public static bool TryGet(BreakableWindow? breakableWindow, [NotNullWhen(true)] out Window? window) + { + window = Get(breakableWindow); + return window != null; + } + + /// + /// Private method to handle the creation of new windows in the server. + /// + /// The that was created. + private static void OnAdded(BreakableWindow structure) + { + if (!Dictionary.ContainsKey(structure)) + _ = new Window(structure); + } + + /// + /// Private method to handle the removal of windows from the server. + /// + /// The that was removed. + private static void OnRemoved(BreakableWindow spawnableStructure) + { + if (Dictionary.TryGetValue(spawnableStructure, out Window structure)) + structure.OnRemove(); + } +} diff --git a/LabApi/Features/Wrappers/Facility/Structures/Workstation.cs b/LabApi/Features/Wrappers/Facility/Structures/Workstation.cs index e947221f..10d9f0ed 100644 --- a/LabApi/Features/Wrappers/Facility/Structures/Workstation.cs +++ b/LabApi/Features/Wrappers/Facility/Structures/Workstation.cs @@ -16,29 +16,42 @@ public class Workstation : Structure /// /// Contains all the cached workstations, accessible through their . /// - public new static Dictionary Dictionary = []; + public static new Dictionary Dictionary { get; } = []; /// /// A reference to all instances. /// - public new static IReadOnlyCollection List => Dictionary.Values; + public static new IReadOnlyCollection List => Dictionary.Values; /// - /// An internal constructor to prevent external instantiation. + /// Gets the workstation wrapper from the , or creates a new one if it doesn't exist and the provided was not . /// - /// The base object. - internal Workstation(SpawnableStructure spawnableStructure) : base(spawnableStructure) + /// The of the workstation. + /// The requested wrapper or . + [return: NotNullIfNotNull(nameof(spawnableStructure))] + public static new Workstation? Get(SpawnableStructure? spawnableStructure) { - BaseController = spawnableStructure.GetComponent(); + if (spawnableStructure == null) + { + return null; + } + + return Dictionary.TryGetValue(spawnableStructure, out Workstation found) ? found : (Workstation)CreateStructureWrapper(spawnableStructure); } /// - /// An internal method to remove itself from the cache when the base object is destroyed. + /// An internal constructor to prevent external instantiation. /// - internal override void OnRemove() + /// The base object. + internal Workstation(SpawnableStructure spawnableStructure) + : base(spawnableStructure) { - base.OnRemove(); - Dictionary.Remove(Base); + BaseController = spawnableStructure.GetComponent(); + + if (CanCache) + { + Dictionary.Add(spawnableStructure, this); + } } /// @@ -85,16 +98,11 @@ public void Interact(Player player) => BaseController.ServerInteract(player.ReferenceHub, BaseController.ActivateCollider.ColliderId); /// - /// Gets the workstation wrapper from the , or creates a new one if it doesn't exist and the provided was not . + /// An internal method to remove itself from the cache when the base object is destroyed. /// - /// The of the workstation. - /// The requested wrapper or . - [return: NotNullIfNotNull(nameof(spawnableStructure))] - public static new Workstation? Get(SpawnableStructure? spawnableStructure) + internal override void OnRemove() { - if (spawnableStructure == null) - return null; - - return Dictionary.TryGetValue(spawnableStructure, out Workstation found) ? found : (Workstation)CreateStructureWrapper(spawnableStructure); + base.OnRemove(); + Dictionary.Remove(Base); } } diff --git a/LabApi/Features/Wrappers/Facility/Warhead.cs b/LabApi/Features/Wrappers/Facility/Warhead.cs index 5a0eca5d..3ef016a2 100644 --- a/LabApi/Features/Wrappers/Facility/Warhead.cs +++ b/LabApi/Features/Wrappers/Facility/Warhead.cs @@ -1,7 +1,6 @@ using GameCore; using Generators; using LabApi.Events.Handlers; -using MapGeneration; using Mirror; using System; using System.Collections.Generic; @@ -14,13 +13,6 @@ namespace LabApi.Features.Wrappers; /// public static class Warhead { - [InitializeWrapper] - internal static void Initialize() - { - ServerEvents.WaitingForPlayers += OnWaitingForPlayers; - // TODO: Might want to handle this a different way as we are missing on destroy - } - /// /// The base . /// Null if they have not been created yet, see . @@ -61,7 +53,9 @@ public static bool LeverStatus set { if (BaseNukesitePanel != null) + { BaseNukesitePanel.Networkenabled = value; + } } } @@ -83,7 +77,9 @@ public static bool IsLocked set { if (BaseController != null) + { BaseController.IsLocked = value; + } } } @@ -103,11 +99,7 @@ public static bool IsLocked public static float DetonationTime { get => AlphaWarheadController.TimeUntilDetonation; - set - { - if (BaseController != null) - BaseController.ForceTime(value); - } + set => BaseController?.ForceTime(value); } /// @@ -119,10 +111,40 @@ public static double CooldownTime set { if (BaseController != null) + { BaseController.NetworkCooldownEndTime = NetworkTime.time + value; + } } } + /// + /// Forces DMS sequence to count down even if conditions are not met. + /// + public static bool ForceCountdownToggle + { + get => DeadmanSwitch.ForceCountdownToggle; + set => DeadmanSwitch.ForceCountdownToggle = value; + } + + /// + /// Indicates how much time is left for the DMS to activate. + /// Value is capped by . + /// + public static float DeadManSwitchRemaining + { + get => DeadmanSwitch.CountdownTimeLeft; + set => DeadmanSwitch.CountdownTimeLeft = value; + } + + /// + /// Indicates the amount of time it takes for the DMS to activate. + /// + public static float DeadManSwitchMaxTime + { + get => DeadmanSwitch.CountdownMaxTime; + set => DeadmanSwitch.CountdownMaxTime = value; + } + /// /// Gets or sets the value for which to use. /// @@ -135,20 +157,25 @@ public static DetonationScenario Scenario get { if (BaseController == null) - return new DetonationScenario(); + { + return default; + } return ScenarioType switch { WarheadScenarioType.Start => StartScenarios[BaseController.Info.ScenarioId], WarheadScenarioType.Resume => ResumeScenarios[BaseController.Info.ScenarioId], WarheadScenarioType.DeadmanSwitch => DeadmanSwitchScenario, - _ => new DetonationScenario() + _ => default, }; } + set { if (BaseController == null) + { return; + } if (value.Equals(default)) { @@ -197,7 +224,7 @@ public static DetonationScenario Scenario /// /// Gets the deadman switch scenario. /// - public static DetonationScenario DeadmanSwitchScenario { get; private set; } = new DetonationScenario(); + public static DetonationScenario DeadmanSwitchScenario { get; private set; } = default; /// /// Starts the detonation countdown. @@ -234,7 +261,9 @@ public static void Detonate() public static void OpenBlastDoors() { foreach (BlastDoor door in BlastDoor.Instances) + { door.ServerSetTargetState(true); + } } /// @@ -243,7 +272,9 @@ public static void OpenBlastDoors() public static void CloseBlastDoors() { foreach (BlastDoor door in BlastDoor.Instances) + { door.ServerSetTargetState(false); + } } /// @@ -251,6 +282,17 @@ public static void CloseBlastDoors() /// public static void Shake() => BaseController?.RpcShake(false); + /// + /// Initializes the warhead class. + /// + [InitializeWrapper] + internal static void Initialize() + { + ServerEvents.WaitingForPlayers += OnWaitingForPlayers; + + // TODO: Might want to handle this a different way as we are missing on destroy + } + /// /// Handles the creation of the warhead components. /// @@ -258,7 +300,7 @@ private static void OnWaitingForPlayers() { BaseOutsidePanel = UnityEngine.Object.FindObjectOfType(); - StartScenarios = BaseController.StartScenarios.Select((x, i) => new DetonationScenario(x, (byte)i, WarheadScenarioType.Start)).ToArray(); + StartScenarios = BaseController!.StartScenarios.Select((x, i) => new DetonationScenario(x, (byte)i, WarheadScenarioType.Start)).ToArray(); ResumeScenarios = BaseController.ResumeScenarios.Select((x, i) => new DetonationScenario(x, (byte)i, WarheadScenarioType.Resume)).ToArray(); DeadmanSwitchScenario = new DetonationScenario(BaseController.DeadmanSwitchScenario, 0, WarheadScenarioType.DeadmanSwitch); } @@ -276,20 +318,6 @@ private static void OnMapDestroyed() /// public readonly struct DetonationScenario { - /// - /// Internal constructor to prevent external instantiation. - /// - /// The . - /// The id of the scenario. - /// The . - internal DetonationScenario(AlphaWarheadController.DetonationScenario detonationScenario, byte id, WarheadScenarioType type) - { - TimeToDetonate = detonationScenario.TimeToDetonate; - AdditionalTime = detonationScenario.AdditionalTime; - Type = type; - Id = id; - } - /// /// The countdown time announced. /// @@ -310,6 +338,21 @@ internal DetonationScenario(AlphaWarheadController.DetonationScenario detonation /// public readonly byte Id; + /// + /// Internal constructor to prevent external instantiation. + /// + /// The . + /// The id of the scenario. + /// The . + internal DetonationScenario(AlphaWarheadController.DetonationScenario detonationScenario, byte id, WarheadScenarioType type) + { + TimeToDetonate = detonationScenario.TimeToDetonate; + // TODO: Remove the cast on 2.0.0 and change additional time to float + AdditionalTime = (int)detonationScenario.AdditionalTime; + Type = type; + Id = id; + } + /// /// The actual time it takes for the warhead to detonate. /// diff --git a/LabApi/Features/Wrappers/Items/AmmoItem.cs b/LabApi/Features/Wrappers/Items/AmmoItem.cs index 6c7fe2c4..bf1ed142 100644 --- a/LabApi/Features/Wrappers/Items/AmmoItem.cs +++ b/LabApi/Features/Wrappers/Items/AmmoItem.cs @@ -14,12 +14,28 @@ public class AmmoItem : Item /// /// Contains all the cached ammo items, accessible through their . /// - public new static Dictionary Dictionary { get; } = []; + public static new Dictionary Dictionary { get; } = []; /// /// A reference to all instances of . /// - public new static IReadOnlyCollection List => Dictionary.Values; + public static new IReadOnlyCollection List => Dictionary.Values; + + /// + /// Gets the ammo item wrapper from the or creates a new one if it doesn't exist and the provided was not null. + /// + /// The of the item. + /// The requested item or null. + [return: NotNullIfNotNull(nameof(baseAmmoItem))] + public static AmmoItem? Get(BaseAmmoItem? baseAmmoItem) + { + if (baseAmmoItem == null) + { + return null; + } + + return Dictionary.TryGetValue(baseAmmoItem, out AmmoItem item) ? item : (AmmoItem)CreateItemWrapper(baseAmmoItem); + } /// /// An internal constructor to prevent external instantiation. @@ -31,16 +47,9 @@ internal AmmoItem(BaseAmmoItem baseAmmoItem) Base = baseAmmoItem; if (CanCache) + { Dictionary.Add(baseAmmoItem, this); - } - - /// - /// An internal method to remove itself from the cache when the base object is destroyed. - /// - internal override void OnRemove() - { - base.OnRemove(); - Dictionary.Remove(Base); + } } /// @@ -49,16 +58,11 @@ internal override void OnRemove() public new BaseAmmoItem Base { get; } /// - /// Gets the ammo item wrapper from the or creates a new one if it doesn't exist and the provided was not null. + /// An internal method to remove itself from the cache when the base object is destroyed. /// - /// The of the item. - /// The requested item or null. - [return: NotNullIfNotNull(nameof(baseAmmoItem))] - public static AmmoItem? Get(BaseAmmoItem? baseAmmoItem) + internal override void OnRemove() { - if (baseAmmoItem == null) - return null; - - return Dictionary.TryGetValue(baseAmmoItem, out AmmoItem item) ? item : (AmmoItem)CreateItemWrapper(baseAmmoItem); + base.OnRemove(); + Dictionary.Remove(Base); } } diff --git a/LabApi/Features/Wrappers/Items/BodyArmorItem.cs b/LabApi/Features/Wrappers/Items/BodyArmorItem.cs index 07d1bd63..8f106981 100644 --- a/LabApi/Features/Wrappers/Items/BodyArmorItem.cs +++ b/LabApi/Features/Wrappers/Items/BodyArmorItem.cs @@ -1,5 +1,5 @@ -using System; -using InventorySystem.Items.Armor; +using InventorySystem.Items.Armor; +using System; using System.Collections.Generic; using System.Diagnostics.CodeAnalysis; @@ -13,12 +13,28 @@ public class BodyArmorItem : Item /// /// Contains all the cached body armor items, accessible through their . /// - public new static Dictionary Dictionary { get; } = []; + public static new Dictionary Dictionary { get; } = []; /// /// A reference to all instances of . /// - public new static IReadOnlyCollection List => Dictionary.Values; + public static new IReadOnlyCollection List => Dictionary.Values; + + /// + /// Gets the body armor item wrapper from the or creates a new one if it doesn't exist and the provided was not null. + /// + /// The of the item. + /// The requested item or null. + [return: NotNullIfNotNull(nameof(bodyArmor))] + public static BodyArmorItem? Get(BodyArmor? bodyArmor) + { + if (bodyArmor == null) + { + return null; + } + + return Dictionary.TryGetValue(bodyArmor, out BodyArmorItem item) ? item : (BodyArmorItem)CreateItemWrapper(bodyArmor); + } /// /// An internal constructor to prevent external instantiation. @@ -30,16 +46,9 @@ internal BodyArmorItem(BodyArmor bodyArmor) Base = bodyArmor; if (CanCache) + { Dictionary.Add(bodyArmor, this); - } - - /// - /// An internal method to remove itself from the cache when the base object is destroyed. - /// - internal override void OnRemove() - { - base.OnRemove(); - Dictionary.Remove(Base); + } } /// @@ -63,7 +72,7 @@ public bool RemoveExcessOnDrop public bool IsMovementModifierActive => Base.MovementModifierActive; /// - /// Gets the movement speed multiplier after being processed by . + /// Gets the movement speed multiplier after being processed by . /// public float ActualMovementSpeedMultiplier => Base.MovementSpeedMultiplier; @@ -73,21 +82,16 @@ public bool RemoveExcessOnDrop public bool IsStaminaModifierActive => Base.StaminaModifierActive; /// - /// Gets the stamina usage multiplier after being processed by . + /// Gets the stamina usage multiplier after being processed by . /// public float ActualStaminaUsageMultiplier => Base.StaminaUsageMultiplier; /// - /// Gets the body armor item wrapper from the or creates a new one if it doesn't exist and the provided was not null. + /// An internal method to remove itself from the cache when the base object is destroyed. /// - /// The of the item. - /// The requested item or null. - [return: NotNullIfNotNull(nameof(bodyArmor))] - public static BodyArmorItem? Get(BodyArmor? bodyArmor) + internal override void OnRemove() { - if (bodyArmor == null) - return null; - - return Dictionary.TryGetValue(bodyArmor, out BodyArmorItem item) ? item : (BodyArmorItem)CreateItemWrapper(bodyArmor); + base.OnRemove(); + Dictionary.Remove(Base); } } diff --git a/LabApi/Features/Wrappers/Items/CoinItem.cs b/LabApi/Features/Wrappers/Items/CoinItem.cs index e2fd85e1..75a99d07 100644 --- a/LabApi/Features/Wrappers/Items/CoinItem.cs +++ b/LabApi/Features/Wrappers/Items/CoinItem.cs @@ -17,12 +17,28 @@ public class CoinItem : Item /// /// Contains all the cached coin items, accessible through their . /// - public new static Dictionary Dictionary { get; } = []; + public static new Dictionary Dictionary { get; } = []; /// /// A reference to all instances of . /// - public new static IReadOnlyCollection List => Dictionary.Values; + public static new IReadOnlyCollection List => Dictionary.Values; + + /// + /// Gets the coin item wrapper from the or creates a new one if it doesn't exist and the provided was not null. + /// + /// The of the item. + /// The requested item or null. + [return: NotNullIfNotNull(nameof(coin))] + public static CoinItem? Get(Coin? coin) + { + if (coin == null) + { + return null; + } + + return Dictionary.TryGetValue(coin, out CoinItem item) ? item : (CoinItem)CreateItemWrapper(coin); + } /// /// An internal constructor to prevent external instantiation. @@ -34,16 +50,9 @@ internal CoinItem(Coin coin) Base = coin; if (CanCache) + { Dictionary.Add(coin, this); - } - - /// - /// An internal method to remove itself from the cache when the base object is destroyed. - /// - internal override void OnRemove() - { - base.OnRemove(); - Dictionary.Remove(Base); + } } /// @@ -64,16 +73,11 @@ internal override void OnRemove() public double? LastFlipTime => Coin.FlipTimes.TryGetValue(Serial, out double time) ? Math.Abs(time) : null; /// - /// Gets the coin item wrapper from the or creates a new one if it doesn't exist and the provided was not null. + /// An internal method to remove itself from the cache when the base object is destroyed. /// - /// The of the item. - /// The requested item or null. - [return: NotNullIfNotNull(nameof(coin))] - public static CoinItem? Get(Coin? coin) + internal override void OnRemove() { - if (coin == null) - return null; - - return Dictionary.TryGetValue(coin, out CoinItem item) ? item : (CoinItem)CreateItemWrapper(coin); + base.OnRemove(); + Dictionary.Remove(Base); } } diff --git a/LabApi/Features/Wrappers/Items/Firearm/FirearmItem.cs b/LabApi/Features/Wrappers/Items/Firearm/FirearmItem.cs index 14a0480d..ed379556 100644 --- a/LabApi/Features/Wrappers/Items/Firearm/FirearmItem.cs +++ b/LabApi/Features/Wrappers/Items/Firearm/FirearmItem.cs @@ -1,23 +1,89 @@ -using InventorySystem.Items.Firearms; +using Generators; +using InventorySystem.Items.Firearms; +using InventorySystem.Items.Firearms.Attachments; +using InventorySystem.Items.Firearms.Attachments.Components; +using InventorySystem.Items.Firearms.Modules; +using LabApi.Features.Console; +using System; using System.Collections.Generic; using System.Diagnostics.CodeAnalysis; namespace LabApi.Features.Wrappers; /// -/// The wrapper representing . +/// The wrapper representing . +/// Firearms are functioning as they close as they would in real life. +/// This means that there are properties for whether the bolt is closed or opened, whether the hammer is cocked for specific firearms, whether the magazine is inserted and so many other properties you may need to be aware of when adjusting this firearm item. /// public class FirearmItem : Item { + /// + /// Contains all the handlers for constructing wrappers for the associated base game types. + /// + private static readonly Dictionary> TypeWrappers = []; + /// /// Contains all the cached firearm items, accessible through their . /// - public new static Dictionary Dictionary { get; } = []; + public static new Dictionary Dictionary { get; } = []; /// /// A reference to all instances of . /// - public new static IReadOnlyCollection List => Dictionary.Values; + public static new IReadOnlyCollection List => Dictionary.Values; + + /// + /// Gets the firearm item wrapper from the or creates a new one if it doesn't exist and the provided was not null. + /// + /// The of the item. + /// The requested item or null. + [return: NotNullIfNotNull(nameof(firearm))] + public static FirearmItem? Get(Firearm? firearm) + { + if (firearm == null) + { + return null; + } + + return Dictionary.TryGetValue(firearm, out FirearmItem item) ? item : CreateFirearmWrapper(firearm); + } + + /// + /// Creates a firearm wrapper or it's subtype. + /// + /// The base game firearm. + /// Firearm wrapper object. + internal static FirearmItem CreateFirearmWrapper(Firearm firearm) + { + if (!TypeWrappers.TryGetValue(firearm.ItemTypeId, out Func ctor)) + { + return new FirearmItem(firearm); + } + + return ctor(firearm); + } + + /// + /// Initializes the class by subscribing to events and registers derived wrappers. + /// + [InitializeWrapper] + internal static void InitializeFirearmWrappers() + { + Register(ItemType.ParticleDisruptor, (x) => new ParticleDisruptorItem((ParticleDisruptor)x)); + Register(ItemType.GunRevolver, (x) => new RevolverFirearm(x)); + Register(ItemType.GunSCP127, (x) => new Scp127Firearm(x)); + Register(ItemType.GunShotgun, (x) => new ShotgunFirearm(x)); + } + + /// + /// A private method to handle the addition of wrapper handlers. + /// + /// Item type of the target firearm. + /// A handler to construct the wrapper with the base game instance. + private static void Register(ItemType itemType, Func constructor) + { + TypeWrappers.Add(itemType, x => constructor(x)); + } /// /// An internal constructor to prevent external instantiation. @@ -29,34 +95,552 @@ internal FirearmItem(Firearm firearm) Base = firearm; if (CanCache) + { Dictionary.Add(firearm, this); + } + + CacheModules(); } /// - /// An internal method to remove itself from the cache when the base object is destroyed. + /// The base object. /// - internal override void OnRemove() + public new Firearm Base { get; } + + /// + /// Gets the total firearm's weight including attachments in kilograms. + /// + public new float Weight => Base.Weight; + + /// + /// Gets the total length of this firearm in inches. + /// + public float Length => Base.Length; + + /// + /// Gets the weight of the firearm in kilograms without any attachments. + /// + public float BaseWeight => Base.BaseLength; + + /// + /// Gets the length of the firearm in inches without any attachments. + /// + public float BaseLength => Base.BaseLength; + + /// + /// Gets whether the player is currently reloading this firearm. + /// + public bool IsReloading => ReloaderModule.IsReloading; + + /// + /// Gets whether the player is currently unloading this firearm. + /// + public bool IsUnloading => ReloaderModule.IsUnloading; + + /// + /// Gets whether the player is either reloading or unloading this firearm. + /// + public bool IsReloadingOrUnloading => ReloaderModule.IsReloadingOrUnloading; + + /// + /// Gets whether the player can reload this firearm. + /// + public bool CanReload => IReloadUnloadValidatorModule.ValidateReload(Base) && !IsReloadingOrUnloading; + + /// + /// Gets whether the player can unload this firearm. + /// + public bool CanUnload => IReloadUnloadValidatorModule.ValidateUnload(Base) && !IsReloadingOrUnloading; + + /// + /// Gets the firearm's ammo type. + /// + /// + /// May be if the firearm item is no longer valid or this firearm is . + /// + public ItemType AmmoType { - base.OnRemove(); - Dictionary.Remove(Base); + get + { + if (AmmoContainerModule == null) + { + return ItemType.None; + } + + return AmmoContainerModule.AmmoType; + } } /// - /// The base object. + /// Gets or sets whether the firearm's hammer is cocked. /// - public new Firearm Base { get; } + /// + /// Every automatic firearm requires to be and to be to be fired properly with chambered ammo. + /// + public virtual bool Cocked + { + get + { + if (ActionModule is AutomaticActionModule actionModule) + { + return actionModule.Cocked; + } + + return false; + } + + set + { + if (ActionModule is not AutomaticActionModule actionModule) + { + Logger.Error($"Unable to set {nameof(Cocked)} as this firearm's {nameof(IActionModule)} is invalid"); + return; + } + + actionModule.Cocked = value; + actionModule.ServerResync(); + } + } /// - /// Gets the firearm item wrapper from the or creates a new one if it doesn't exist and the provided was not null. + /// Gets or sets whether the firearm's bolt is in rear position. + /// This is only used by closed-bolt firearms. /// - /// The of the item. - /// The requested item or null. - [return: NotNullIfNotNull(nameof(firearm))] - public static FirearmItem? Get(Firearm? firearm) + public virtual bool BoltLocked { - if (firearm == null) - return null; + get + { + if (ActionModule is AutomaticActionModule actionModule) + { + return actionModule.BoltLocked; + } + + return false; + } + + set + { + if (ActionModule is not AutomaticActionModule actionModule) + { + Logger.Error($"Unable to set {nameof(BoltLocked)} as this firearm's {nameof(IActionModule)} is invalid"); + return; + } + + actionModule.BoltLocked = value; + actionModule.ServerResync(); + } + } + + /// + /// Gets if the firearm fires from an open bolt, that means the chambers are not capable of storing any ammo in . + /// + public virtual bool OpenBolt + { + get + { + if (ActionModule is AutomaticActionModule actionModule) + { + return actionModule.OpenBolt; + } + + return false; + } + } + + /// + /// Gets the firerate with current attachment's modifiers applied. + /// + public float Firerate + { + get + { + if (ActionModule != null) + { + return ActionModule.DisplayCyclicRate; + } + + return 0; + } + } + + /// + /// Gets or sets the attachments code for this firearm.
+ /// Attachments code is a binary representation of which are enabled/disabled.
+ /// For validation, see . + ///
+ public uint AttachmentsCode + { + get => Base.GetCurrentAttachmentsCode(); + set + { + Base.ApplyAttachmentsCode(value, true); + Base.ServerResendAttachmentCode(); + } + } + + /// + /// Gets or sets whether this firearm has inserted magazine.
+ /// An empty magazine is inserted when set to .
+ /// Remaining ammo from the magazine is inserted back into player's inventory when removed. + ///
+ /// + /// Firearms with no external or internal magazine will always return . + /// + public virtual bool MagazineInserted + { + get + { + if (MagazineControllerModule == null) + { + return false; + } + + return MagazineControllerModule.MagazineInserted; + } + + set + { + if (MagazineControllerModule is not MagazineModule magazineModule) + { + Logger.Error($"Unable to set {nameof(MagazineInserted)} as this firearm's {nameof(IMagazineControllerModule)} is null"); + return; + } + + if (value) + { + magazineModule.ServerInsertEmptyMagazine(); + } + else + { + magazineModule.ServerRemoveMagazine(); + } + } + } + + /// + /// Gets or sets the stored ammo in a ammo container for this firearm. + /// + /// + /// Ammo in magazine beyond when pickup up this firearm again from the ground is added back to player's inventory. + /// + public virtual int StoredAmmo + { + get + { + if (AmmoContainerModule == null) + { + return 0; + } + + return AmmoContainerModule.AmmoStored; + } + + set + { + if (AmmoContainerModule == null) + { + Logger.Error($"Unable to set {nameof(StoredAmmo)} as this firearm's {nameof(IPrimaryAmmoContainerModule)} is null"); + return; + } + + int toAdd = value - AmmoContainerModule.AmmoStored; + AmmoContainerModule.ServerModifyAmmo(toAdd); + } + } + + /// + /// Gets the maximum ammo the firearm can have in its ammo container. Attachment modifiers are taken into account when calculating it. + /// + public int MaxAmmo + { + get + { + if (AmmoContainerModule == null) + { + return 0; + } + + return AmmoContainerModule.AmmoMax; + } + } + + /// + /// Gets or sets the current ammo in the chamber. + /// firearms do not use this value and take ammo directly from it's ammo container. + /// + public virtual int ChamberedAmmo + { + get + { + if (ActionModule is AutomaticActionModule actionModule) + { + return actionModule.AmmoStored; + } + + return 0; + } + + set + { + if (ActionModule is not AutomaticActionModule actionModule) + { + Logger.Error($"Unable to set {nameof(ChamberedAmmo)} as this firearm's {nameof(IActionModule)} is not valid."); + return; + } + + actionModule.AmmoStored = value; + actionModule.ServerResync(); + } + } + + /// + /// Gets or sets the maximum ammo in chamber. + /// Visual side may be incorrect. + /// For automatic firearms, this value won't properly sync above 16 as only 4 bits are used for the chambered sync to the client. + /// + public virtual int ChamberMax + { + get + { + if (ActionModule is AutomaticActionModule actionModule) + { + return actionModule.ChamberSize; + } + + return 0; + } + + set + { + if (ActionModule is not AutomaticActionModule actionModule) + { + Logger.Error($"Unable to set {nameof(ChamberMax)} as this firearm's {nameof(IActionModule)} is not valid."); + return; + } + + actionModule.ChamberSize = value; + } + } + + /// + /// Gets or sets whether the firearm's flashlight attachment is enabled and is emitting light. + /// + public bool FlashlightEnabled + { + get + { + foreach (Attachment attachment in Attachments) + { + if (attachment is not FlashlightAttachment flashlightAttachment) + { + continue; + } + + return flashlightAttachment.IsEnabled && flashlightAttachment.IsEmittingLight; + } + + return false; + } + + set + { + foreach (Attachment attachment in Attachments) + { + if (attachment is not FlashlightAttachment flashlightAttachment) + { + continue; + } + + flashlightAttachment.ServerSendStatus(value); + } + } + } + + /// + /// All attachment used by this firearm.
+ /// Set the attachments status using + ///
+ public Attachment[] Attachments => Base.Attachments; + + /// + /// All modules used by this firearm. + /// Modules are the main scripts defining all of the functionality of a firearm. + /// + public ModuleBase[] Modules => Base.Modules; + + /// + /// Gets all available attachments names of this firearms. + /// + public IEnumerable AvailableAttachmentsNames + { + get + { + foreach (Attachment attachment in Attachments) + { + yield return attachment.Name; + } + } + } + + /// + /// Gets all enabled attachments of this firearm. + /// + public IEnumerable ActiveAttachments + { + get + { + foreach (Attachment attachment in Attachments) + { + if (attachment.IsEnabled) + { + yield return attachment; + } + } + } + } + + /// + /// Module for the magazine. + /// + protected IPrimaryAmmoContainerModule AmmoContainerModule { get; set; } = null!; - return Dictionary.TryGetValue(firearm, out FirearmItem item) ? item : (FirearmItem)CreateItemWrapper(firearm); + /// + /// Module for firearm's chamber. + /// + protected IActionModule ActionModule { get; set; } = null!; + + /// + /// Module for handling gun's reloading and unloading. + /// + protected IReloaderModule ReloaderModule { get; set; } = null!; + + /// + /// Module for handling gun's magazine. + /// + protected IMagazineControllerModule MagazineControllerModule { get; set; } = null!; + + /// + /// Gets whether the provided attachments code is valid and can be applied. + /// + /// The code to validate. + /// Whether the code is valid and can be applied. + public bool CheckAttachmentsCode(uint code) => ValidateAttachmentsCode(code) == code; + + /// + /// Gets whether the provided attachment names are valid together and only 1 belongs to each category. + /// + /// Attachment names. + /// Whether the attachments can be applied together. + public bool CheckAttachmentsCode(params AttachmentName[] attachments) + { + uint rawCode = GetCodeFromAttachmentNamesRaw(attachments); + + return rawCode == ValidateAttachmentsCode(rawCode); + } + + /// + /// Gets validated attachments code. + /// Validation of the code is following: + /// + /// Only 1 attachments from the same is applied. If multiple ones are enabled, only the first one is selected. + /// without any attachents assigned sets the first one to enabled. + /// + /// + /// The code to be validated. + /// Validated code with missing attachments added for category and only 1 attachment per category selected. + public uint ValidateAttachmentsCode(uint code) => Base.ValidateAttachmentsCode(code); + + /// + /// Array of attachment names to be applied and validated. + public uint ValidateAttachmentsCode(params AttachmentName[] attachments) + { + return ValidateAttachmentsCode(GetCodeFromAttachmentNamesRaw(attachments)); + } + + /// + /// Gets attachments code from s. This value is NOT validated. + /// + /// Attachment names. + /// Unchecked attachments code. + public uint GetCodeFromAttachmentNamesRaw(AttachmentName[] attachments) + { + uint resultCode = 0; + + uint bin = 1; + foreach (Attachment attachment in Attachments) + { + if (attachments.Contains(attachment.Name)) + { + resultCode += bin; + } + + bin *= 2; + } + + return resultCode; + } + + /// + /// Reloads the firearm if is . + /// + /// Whether the player started to reload. + public bool Reload() + { + if (ReloaderModule is not AnimatorReloaderModuleBase animatorModule) + { + Logger.Error($"Unable to reload this firearm as it's animator module is invalid"); + return false; + } + + return animatorModule.ServerTryReload(); + } + + /// + /// Unloads the firearm if is . + /// + /// Whether the player started the unload. + public bool Unload() + { + if (ReloaderModule is not AnimatorReloaderModuleBase animatorModule) + { + Logger.Error($"Unable to unload this firearm as it's animator module is invalid"); + return false; + } + + return animatorModule.ServerTryUnload(); + } + + /// + /// An internal method to remove itself from the cache when the base object is destroyed. + /// + internal override void OnRemove() + { + base.OnRemove(); + Dictionary.Remove(Base); + } + + /// + /// Caches modules used by the firearm. + /// + protected virtual void CacheModules() + { + foreach (ModuleBase module in Modules) + { + switch (module) + { + case IPrimaryAmmoContainerModule ammoModule: + AmmoContainerModule = ammoModule; + continue; + case IActionModule actionModule: + ActionModule = actionModule; + continue; + case IReloaderModule reloaderModule: + ReloaderModule = reloaderModule; + continue; + case IMagazineControllerModule magazineControllerModule: + MagazineControllerModule = magazineControllerModule; + continue; + } + } } } diff --git a/LabApi/Features/Wrappers/Items/Firearm/ParticleDisruptorItem.cs b/LabApi/Features/Wrappers/Items/Firearm/ParticleDisruptorItem.cs deleted file mode 100644 index f62c5933..00000000 --- a/LabApi/Features/Wrappers/Items/Firearm/ParticleDisruptorItem.cs +++ /dev/null @@ -1,62 +0,0 @@ -using InventorySystem.Items.Firearms; -using System.Collections.Generic; -using System.Diagnostics.CodeAnalysis; - -namespace LabApi.Features.Wrappers; - -/// -/// The wrapper representing . -/// -public class ParticleDisruptorItem : FirearmItem -{ - /// - /// Contains all the cached particle disruptor items, accessible through their . - /// - public new static Dictionary Dictionary { get; } = []; - - /// - /// A reference to all instances of . - /// - public new static IReadOnlyCollection List => Dictionary.Values; - - /// - /// An internal constructor to prevent external instantiation. - /// - /// The base object. - internal ParticleDisruptorItem(ParticleDisruptor particleDisruptor) - : base(particleDisruptor) - { - Base = particleDisruptor; - - if (CanCache) - Dictionary.Add(particleDisruptor, this); - } - - /// - /// An internal method to remove itself from the cache when the base object is destroyed. - /// - internal override void OnRemove() - { - base.OnRemove(); - Dictionary.Remove(Base); - } - - /// - /// The base object. - /// - public new ParticleDisruptor Base { get; } - - /// - /// Gets the particle disruptor item wrapper from the or creates a new one if it doesn't exist and the provided was not null. - /// - /// The of the item. - /// The requested item or null. - [return: NotNullIfNotNull(nameof(particleDisruptor))] - public static ParticleDisruptorItem? Get(ParticleDisruptor? particleDisruptor) - { - if (particleDisruptor == null) - return null; - - return Dictionary.TryGetValue(particleDisruptor, out ParticleDisruptorItem item) ? item : (ParticleDisruptorItem)CreateItemWrapper(particleDisruptor); - } -} diff --git a/LabApi/Features/Wrappers/Items/Firearm/SpecialFirearms/ParticleDisruptorItem.cs b/LabApi/Features/Wrappers/Items/Firearm/SpecialFirearms/ParticleDisruptorItem.cs new file mode 100644 index 00000000..15beb29e --- /dev/null +++ b/LabApi/Features/Wrappers/Items/Firearm/SpecialFirearms/ParticleDisruptorItem.cs @@ -0,0 +1,168 @@ +using InventorySystem.Items.Firearms; +using InventorySystem.Items.Firearms.Modules; +using System.Collections.Generic; +using System.Diagnostics.CodeAnalysis; +using static InventorySystem.Items.Firearms.Modules.DisruptorActionModule; + +namespace LabApi.Features.Wrappers; + +/// +/// The wrapper representing . +/// +public class ParticleDisruptorItem : FirearmItem +{ + /// + /// Contains all the cached particle disruptor items, accessible through their . + /// + public static new Dictionary Dictionary { get; } = []; + + /// + /// A reference to all instances of . + /// + public static new IReadOnlyCollection List => Dictionary.Values; + + /// + /// Gets the particle disruptor item wrapper from the or creates a new one if it doesn't exist and the provided was not . + /// + /// The of the item. + /// The requested item or . + [return: NotNullIfNotNull(nameof(particleDisruptor))] + public static ParticleDisruptorItem? Get(ParticleDisruptor? particleDisruptor) + { + if (particleDisruptor == null) + { + return null; + } + + return Dictionary.TryGetValue(particleDisruptor, out ParticleDisruptorItem item) ? item : (ParticleDisruptorItem)CreateItemWrapper(particleDisruptor); + } + + private DisruptorModeSelector _selectorModule = null!; + + /// + /// An internal constructor to prevent external instantiation. + /// + /// The base object. + internal ParticleDisruptorItem(ParticleDisruptor particleDisruptor) + : base(particleDisruptor) + { + Base = particleDisruptor; + + if (CanCache) + { + Dictionary.Add(particleDisruptor, this); + } + } + + /// + /// The base object. + /// + public new ParticleDisruptor Base { get; } + + /// + /// Gets the current firing state. + /// + public FiringState FiringState + { + get + { + if (ActionModule is DisruptorActionModule actionModule) + { + return actionModule.CurFiringState; + } + + return FiringState.None; + } + } + + /// + /// Gets whether the disruptor has single-shot mode selected. + /// + public bool SingleShotMode + { + get + { + if (_selectorModule is DisruptorModeSelector selectorModule) + { + return selectorModule.SingleShotSelected; + } + + return false; + } + } + + /// + /// Gets the amount of chambered ammo in the chamber. + /// + public override int ChamberedAmmo + { + get + { + if (ActionModule is DisruptorActionModule actionModule) + { + return actionModule.IsLoaded ? 1 : 0; + } + + return 0; + } + } + + /// + /// Gets the maximum chambered ammo. + /// + public override int ChamberMax + { + get => 1; + } + + /// + /// Gets whether the firearm is cocked and can fire. + /// + public override bool Cocked + { + get + { + if (ActionModule is DisruptorActionModule actionModule) + { + return actionModule.IsLoaded; + } + + return false; + } + } + + /// + public override bool OpenBolt => true; + + /// + /// Destroys this disruptor and plays the destroy animation on the client. + /// + public void Destroy() + { + Base.ServerDestroyItem(); + } + + /// + /// An internal method to remove itself from the cache when the base object is destroyed. + /// + internal override void OnRemove() + { + base.OnRemove(); + Dictionary.Remove(Base); + } + + /// + protected override void CacheModules() + { + base.CacheModules(); + + foreach (ModuleBase module in Modules) + { + if (module is DisruptorModeSelector selectorModule) + { + _selectorModule = selectorModule; + break; + } + } + } +} diff --git a/LabApi/Features/Wrappers/Items/Firearm/SpecialFirearms/RevolverFirearm.cs b/LabApi/Features/Wrappers/Items/Firearm/SpecialFirearms/RevolverFirearm.cs new file mode 100644 index 00000000..8d7454d2 --- /dev/null +++ b/LabApi/Features/Wrappers/Items/Firearm/SpecialFirearms/RevolverFirearm.cs @@ -0,0 +1,195 @@ +using InventorySystem.Items.Firearms; +using InventorySystem.Items.Firearms.Modules; +using LabApi.Features.Console; +using System.Collections.Generic; +using static InventorySystem.Items.Firearms.Modules.CylinderAmmoModule; + +namespace LabApi.Features.Wrappers; + +/// +/// Wrapper for revolver firearm. +/// +public class RevolverFirearm : FirearmItem +{ + private RevolverRouletteModule _rouletteModule = null!; + + /// + /// An internal constructor to prevent external instantiation. + /// + /// The base object. + internal RevolverFirearm(Firearm firearm) + : base(firearm) + { + } + + /// + public override bool OpenBolt => false; + + /// + /// Gets collection of all active chambers. The first chamber is the one aligned with the barrel.
+ /// Each subsequent index corresponds to the next chambers that will become aligned with the barrel when the cylinder rotates in its intended direction.
+ /// Note that double-action revolvers rotate the cylinder right before firing, which means the 0th element isn't necessarily the next round to be fired (unless the revolver is already cocked). + ///
+ public IEnumerable Chambers + { + get + { + if (AmmoContainerModule is CylinderAmmoModule) + { + return GetChambersArrayForSerial(Serial, MaxAmmo); + } + + return []; + } + } + + /// + public override bool Cocked + { + get + { + if (ActionModule is DoubleActionModule actionModule) + { + return actionModule.Cocked; + } + + return false; + } + + set + { + if (ActionModule is not DoubleActionModule actionModule) + { + Logger.Error($"Unable to set {nameof(Cocked)} as the {nameof(DoubleActionModule)} is null."); + return; + } + + actionModule.Cocked = value; + } + } + + /// + /// Gets or sets the stored ammo in a ammo container for this firearm. + /// + /// + /// Stored ammo in revolver firearm cannot exceed its and any additional values are ignored. + /// + public override int StoredAmmo + { + get + { + if (AmmoContainerModule is CylinderAmmoModule ammoModule) + { + return ammoModule.AmmoStored; + } + + return 0; + } + + set + { + if (AmmoContainerModule is not CylinderAmmoModule ammoModule) + { + Logger.Error($"Unable to set {nameof(StoredAmmo)} as the {nameof(CylinderAmmoModule)} is null."); + return; + } + + foreach (Chamber chamber in Chambers) + { + chamber.ServerSyncState = ChamberState.Empty; + } + + ammoModule.ServerModifyAmmo(value); + } + } + + /// + /// Gets or sets the current ammo in the chamber. + /// Revolver's only accounts for the currently aligned chamber with the barrel. Therefore the maximum of chambered ammo is 1 (live round) or 0 (empty / discharged). + /// Any value greater than 1 is counted as live round. + /// + public override int ChamberedAmmo + { + get + { + return GetChambersArrayForSerial(Serial, MaxAmmo)[0].ServerSyncState == ChamberState.Live ? 1 : 0; + } + + set + { + if (ActionModule is not DoubleActionModule actionModule) + { + Logger.Error($"Unable to set {nameof(ChamberedAmmo)} as the {nameof(DoubleActionModule)} is null."); + return; + } + + SetChamberStatus(0, value == 0 ? ChamberState.Empty : ChamberState.Live); + } + } + + /// + /// Sets the status of the chamber at . 0th element is the one currently aligned with the barrel. + /// Indexes of each round are clockwise. + /// + /// Index of the chamber clockwise. Starting at barrel aligned chamber. + /// Target state of the chamber. + public void SetChamberStatus(int index, ChamberState state) + { + if (AmmoContainerModule is not CylinderAmmoModule ammoModule) + { + Logger.Error($"Unable to set chamber status, this firearm doesn't have {nameof(CylinderAmmoModule)}!"); + return; + } + + Chamber[] chambers = GetChambersArrayForSerial(Serial, MaxAmmo); + chambers[index].ServerSyncState = state; + + ammoModule.ServerResync(); + } + + /// + /// Rotates the chamber counter-clockwise (positive numbers) or clockwise (negative numbers) times. + /// No animation is played client-side. + /// + /// The amount of times to rotate this cylinder. + public void Rotate(int amount) + { + if (AmmoContainerModule is not CylinderAmmoModule ammoModule) + { + Logger.Error($"Unable to rotate this cylinder, this firearm doesn't have {nameof(CylinderAmmoModule)}!"); + return; + } + + ammoModule.RotateCylinder(amount); + } + + /// + /// Attempts to spin the revolver if the firearm isn't busy doing something else. + /// + /// Whether the spin request was successful. + public bool TrySpin() + { + if (_rouletteModule is not RevolverRouletteModule ammoModule) + { + Logger.Error($"Unable to spin this cylinder, this firearm doesn't have {nameof(RevolverRouletteModule)}!"); + return false; + } + + return _rouletteModule.ServerTrySpin(); + } + + /// + protected override void CacheModules() + { + base.CacheModules(); + + foreach (ModuleBase module in Modules) + { + if (module is RevolverRouletteModule rouletteModule) + { + _rouletteModule = rouletteModule; + break; + } + } + } +} diff --git a/LabApi/Features/Wrappers/Items/Firearm/SpecialFirearms/Scp127Firearm.cs b/LabApi/Features/Wrappers/Items/Firearm/SpecialFirearms/Scp127Firearm.cs new file mode 100644 index 00000000..22430ef6 --- /dev/null +++ b/LabApi/Features/Wrappers/Items/Firearm/SpecialFirearms/Scp127Firearm.cs @@ -0,0 +1,229 @@ +using InventorySystem.Items.Firearms; +using InventorySystem.Items.Firearms.Modules; +using InventorySystem.Items.Firearms.Modules.Scp127; +using System.Collections.Generic; +using UnityEngine; +using static InventorySystem.Items.Firearms.Modules.Scp127.Scp127VoiceTriggerBase; +using Logger = LabApi.Features.Console.Logger; + +namespace LabApi.Features.Wrappers; + +/// +/// Wrapper for SCP-127. +/// +public class Scp127Firearm : FirearmItem +{ + private Scp127TierManagerModule _tierModule = null!; + + private Scp127VoiceLineManagerModule _voiceModule = null!; + + /// + /// An internal constructor to prevent external instantiation. + /// + /// The base object. + internal Scp127Firearm(Firearm firearm) + : base(firearm) + { + } + + /// + public override bool OpenBolt => false; + + /// + /// Gets all players who are friended with this SCP.
+ /// This means every player who talked with this SCP at least once and is still alive. + ///
+ public IEnumerable Friends + { + get + { + if (!Scp127VoiceLineManagerModule.FriendshipMemory.TryGetValue(Serial, out HashSet friendNetIds)) + { + yield break; + } + + foreach (uint netId in friendNetIds) + { + yield return Player.Get(netId); + } + } + } + + /// + /// Gets or sets the the firearm has. + /// + public Scp127Tier Tier + { + get + { + if (_tierModule == null) + { + return Scp127Tier.Tier1; + } + + return _tierModule.CurTier; + } + + set + { + if (_tierModule == null) + { + Logger.Error($"Unable to set {nameof(Tier)}, {nameof(Scp127TierManagerModule)} is null"); + return; + } + + _tierModule.CurTier = value; + } + } + + /// + /// Gets or sets the experience amount of this firearm. + /// + public float Experience + { + get + { + if (_tierModule == null) + { + return 0; + } + + return _tierModule.ServerExp; + } + + set + { + if (_tierModule == null) + { + Logger.Error($"Unable to set {nameof(Experience)}, {nameof(Scp127TierManagerModule)} is null"); + return; + } + + _tierModule.ServerExp = value; + } + } + + /// + public override int ChamberedAmmo + { + get + { + if (ActionModule is Scp127ActionModule actionModule) + { + return actionModule.AmmoStored; + } + + return 0; + } + + set + { + if (ActionModule is not Scp127ActionModule actionModule) + { + Logger.Error($"Unable to set {nameof(ChamberedAmmo)} as the action module is null."); + return; + } + + actionModule.ChamberSize = value; + actionModule.ServerResync(); + } + } + + /// + public override int ChamberMax + { + get + { + if (ActionModule is Scp127ActionModule actionModule) + { + return actionModule.ChamberSize; + } + + return 0; + } + + set + { + if (ActionModule is not Scp127ActionModule actionModule) + { + Logger.Error($"Unable to set {nameof(ChamberMax)} as the action module is null."); + return; + } + + actionModule.ChamberSize = value; + } + } + + /// + public override bool MagazineInserted + { + get + { + return true; + } + + set + { + if (MagazineControllerModule is Scp127MagazineModule magazineModule) + { + Logger.Error($"Unable to set {nameof(MagazineInserted)} as SCP-127's magazine is not detachable."); + return; + } + } + } + + /// + /// Gets or sets the stored ammo in a ammo container for this firearm. + /// + /// + /// SCP-127 stored ammo is capped at and any values beyond are ignored. + /// + public override int StoredAmmo + { + get => base.StoredAmmo; + set => base.StoredAmmo = value; + } + + /// + /// Plays a specific voiceline defined by the . + /// + /// The target voiceline to play. + /// The priority to play this voice line with. + public void PlayVoiceline(Scp127VoiceLinesTranslation voiceline, VoiceLinePriority priority = VoiceLinePriority.Normal) + { + if (_voiceModule == null) + { + Logger.Error($"Unable to play voiceline, {nameof(Scp127VoiceLineManagerModule)} is null"); + return; + } + + if (!_voiceModule.TryFindVoiceLine(voiceline, out Scp127VoiceTriggerBase trigger, out AudioClip clip)) + { + Logger.Error($"Unable to play voiceline {voiceline} as it wasn't found"); + return; + } + + _voiceModule.ServerSendVoiceLine(trigger, null, clip, (byte)priority); + } + + /// + protected override void CacheModules() + { + base.CacheModules(); + + foreach (ModuleBase module in Modules) + { + if (module is Scp127TierManagerModule tierModule) + { + _tierModule = tierModule; + continue; + } + + if (module is Scp127VoiceLineManagerModule voiceModule) + { + _voiceModule = voiceModule; + continue; + } + } + } +} diff --git a/LabApi/Features/Wrappers/Items/Firearm/SpecialFirearms/ShotgunFirearm.cs b/LabApi/Features/Wrappers/Items/Firearm/SpecialFirearms/ShotgunFirearm.cs new file mode 100644 index 00000000..30c0bb8d --- /dev/null +++ b/LabApi/Features/Wrappers/Items/Firearm/SpecialFirearms/ShotgunFirearm.cs @@ -0,0 +1,150 @@ +using InventorySystem.Items.Firearms; +using InventorySystem.Items.Firearms.Modules; +using LabApi.Features.Console; + +namespace LabApi.Features.Wrappers; + +/// +/// Wrapper for shotgun firearm. +/// +public class ShotgunFirearm : FirearmItem +{ + /// + /// An internal constructor to prevent external instantiation. + /// + /// The base object. + internal ShotgunFirearm(Firearm firearm) + : base(firearm) + { + } + + /// + public override bool OpenBolt => false; + + /// + /// Gets whether any of the hammers is cocked. + /// Sets the cocked status of ALL hammers. + /// + public override bool Cocked + { + get + { + if (ActionModule is PumpActionModule actionModule) + { + return actionModule.SyncCocked == actionModule.Barrels; + } + + return false; + } + + set + { + if (ActionModule is not PumpActionModule actionModule) + { + Logger.Error($"Unable to set {nameof(Cocked)} as it is invalid."); + return; + } + + actionModule.SyncCocked = actionModule.Barrels; + } + } + + /// + /// Gets or sets the amount of currently cocked chambers. + /// + public int CockedChambers + { + get + { + if (ActionModule is PumpActionModule actionModule) + { + return actionModule.SyncCocked; + } + + return 0; + } + + set + { + if (ActionModule is not PumpActionModule actionModule) + { + Logger.Error($"Unable to set {nameof(CockedChambers)} as it is invalid."); + return; + } + + actionModule.SyncCocked = value; + } + } + + /// + /// Gets or sets the amount of barrels this shotgun has. + /// Useful when creating custom weapons.
+ /// It is recommended to set this value before the shotgun has been pumped by the player, otherwise you might need to set and to the correct value. + ///
+ public override int ChamberMax + { + get + { + if (ActionModule is PumpActionModule actionModule) + { + return actionModule.Barrels; + } + + return 0; + } + + set + { + if (ActionModule is not PumpActionModule actionModule) + { + Logger.Error($"Unable to set {nameof(ChamberMax)} as it is invalid."); + return; + } + + actionModule.Barrels = value; + } + } + + /// + /// Gets or sets the current ammo in the barrels. + /// + public override int ChamberedAmmo + { + get + { + if (ActionModule is PumpActionModule actionModule) + { + return actionModule.AmmoStored; + } + + return 0; + } + + set + { + if (ActionModule is not PumpActionModule actionModule) + { + Logger.Error($"Unable to set {nameof(ChamberedAmmo)} as it is null."); + return; + } + + actionModule.AmmoStored = value; + } + } + + /// + /// Schedules pumping for this firearm.
+ /// Value of 0 pumps the firearm instantly. Any value above 0 delays the pump by * 0.5 second. + ///
+ /// The amount of shots that has been fired. Pumping is delayed by * 0.5 second. + public void Pump(int shotsFired = 0) + { + if (ActionModule is not PumpActionModule actionModule) + { + Logger.Error($"Unable to pump {nameof(PumpActionModule)} as it is null."); + return; + } + + actionModule.SchedulePumping(shotsFired); + } +} diff --git a/LabApi/Features/Wrappers/Items/Item.cs b/LabApi/Features/Wrappers/Items/Item.cs index 6cb82c72..202ad2fd 100644 --- a/LabApi/Features/Wrappers/Items/Item.cs +++ b/LabApi/Features/Wrappers/Items/Item.cs @@ -18,10 +18,113 @@ namespace LabApi.Features.Wrappers; /// /// The wrapper representing object. /// -/// Not to be confused with item pickup. +/// Not to be confused with item pickup. /// public class Item { + /// + /// Contains all the handlers for constructing wrappers for the associated base game types. + /// + private static readonly Dictionary> TypeWrappers = []; + + /// + /// Contains all the cached items, accessible through their . + /// + public static Dictionary Dictionary { get; } = []; + + /// + /// A reference to all instances of . + /// + public static IReadOnlyCollection List => Dictionary.Values; + + /// + /// Contains all cached items with their as a key. + /// + private static Dictionary SerialsCache { get; } = []; + + /// + /// Gets the item wrapper from the if it exists and the was not . + /// + /// The of the item. + /// The requested item or null. + [return: NotNullIfNotNull(nameof(itemBase))] + public static Item? Get(ItemBase? itemBase) + { + if (itemBase == null) + { + return null; + } + + return Dictionary.TryGetValue(itemBase, out Item item) ? item : CreateItemWrapper(itemBase); + } + + /// + /// Tries to get the item wrapper from the . + /// + /// The of the item. + /// The requested item. + /// True if the item exists, otherwise false. + public static bool TryGet(ItemBase? itemBase, [NotNullWhen(true)] out Item? item) + { + item = Get(itemBase); + return item != null; + } + + /// + /// Gets the item wrapper or null from . + /// + /// Serial of the item. + /// The requested item. + public static Item? Get(ushort serial) => TryGet(serial, out Item? item) ? item : null; + + /// + /// Gets the item wrapper or null from the based on provided serial number. + /// + /// The serial number of the item. + /// The requested item. + /// Whether the was successfully retrieved, otherwise false. + public static bool TryGet(ushort serial, [NotNullWhen(true)] out Item? item) + { + item = null; + if (SerialsCache.TryGetValue(serial, out item)) + { + return true; + } + + item = List.FirstOrDefault(x => x.Serial == serial); + if (item == null) + { + return false; + } + + SerialsCache[serial] = item; + return true; + } + + /// + /// Gets a pooled list of items having the same . + /// + /// Target type. + /// A List of items. + public static List GetAll(ItemType type) + { + List list = ListPool.Shared.Rent(); + list.AddRange(List.Where(n => n.Type == type)); + return list; + } + + /// + /// Gets a pooled list of items having the same . + /// + /// Target category. + /// A List of items. + public static List GetAll(ItemCategory category) + { + List list = ListPool.Shared.Rent(); + list.AddRange(List.Where(n => n.Category == category)); + return list; + } + /// /// Initializes the class by subscribing to events and registers derived wrappers. /// @@ -43,6 +146,7 @@ internal static void Initialize() Register(x => new MedkitItem(x)); Register(x => new Scp207Item(x)); Register(x => new AntiScp207Item(x)); + Register(x => new Scp021JItem(x)); Register(x => new UsableItem(x)); Register(x => new Scp1576Item(x)); @@ -51,10 +155,12 @@ internal static void Initialize() Register(x => new Scp268Item(x)); Register(x => new Scp1344Item(x)); - Register(x => new FirearmItem(x)); - Register(x => new ParticleDisruptorItem(x)); + Register(FirearmItem.CreateFirearmWrapper); + Register(FirearmItem.CreateFirearmWrapper); + Register(x => new JailbirdItem(x)); Register(x => new CoinItem(x)); + Register(x => new MarshmallowItem(x)); Register(x => new LightItem(x)); Register(x => new FlashlightItem(x)); @@ -64,6 +170,7 @@ internal static void Initialize() Register(x => new AmmoItem(x)); Register(x => new BodyArmorItem(x)); Register(x => new ThrowableItem(x)); + Register(x => new SnowballItem(x)); Register(x => new KeycardItem(x)); Register(x => new KeycardItem(x)); Register(x => new KeycardItem(x)); @@ -71,24 +178,96 @@ internal static void Initialize() } /// - /// Contains all the handlers for constructing wrappers for the associated base game types. + /// Creates a new wrapper from the base item object. /// - private static readonly Dictionary> typeWrappers = []; + /// The base object. + /// The newly created wrapper. + protected static Item CreateItemWrapper(ItemBase item) + { + Type targetType = item.GetType(); + if (!TypeWrappers.TryGetValue(targetType, out Func ctorFunc)) + { +#if DEBUG + Logger.Warn($"Unable to find LabApi wrapper for {nameof(Item)} {targetType.Name}, backup up to base constructor!"); +#endif + return new Item(item); + } + + return ctorFunc.Invoke(item); + } /// - /// Contains all the cached items, accessible through their . + /// A private method to handle the creation of new items in the server. /// - public static Dictionary Dictionary { get; } = []; + /// The created instance. + private static void AddItem(ItemBase item) + { + try + { + if (!Dictionary.ContainsKey(item)) + { + _ = CreateItemWrapper(item); + } + } + catch (Exception e) + { + Logger.InternalError($"Failed to handle item creation with error: {e}"); + } + } /// - /// Contains all cached items with their as a key. + /// A private method to handle the removal of items from the server. /// - private static Dictionary SerialsCache { get; } = []; + /// The to be destroyed instance. + private static void RemoveItem(ItemBase itemBase) + { + try + { + SerialsCache.Remove(itemBase.ItemSerial); + if (Dictionary.TryGetValue(itemBase, out Item item)) + { + Dictionary.Remove(itemBase); + item.OnRemove(); + } + } + catch (Exception e) + { + Console.Logger.InternalError($"Failed to handle item destruction with error: {e}"); + } + } /// - /// A reference to all instances of . + /// A private method to handle the addition of wrapper handlers. /// - public static IReadOnlyCollection List => Dictionary.Values; + /// The derived base game type to handle. + /// A handler to construct the wrapper with the base game instance. + private static void Register(Func constructor) + where T : ItemBase + { + TypeWrappers.Add(typeof(T), x => constructor((T)x)); + } + + /// + /// A private constructor to prevent external instantiation. + /// + /// The of the item. + protected Item(ItemBase itemBase) + { + Base = itemBase; + IsPrefab = InventoryItemLoader.TryGetItem(itemBase.ItemTypeId, out ItemBase prefab) && prefab == itemBase; + + if (CanCache) + { + if (Dictionary.ContainsKey(itemBase)) + { + Console.Logger.InternalError($"Failed to create an item for base: {itemBase}"); + return; + } + + Dictionary[itemBase] = this; + SerialsCache[itemBase.ItemSerial] = this; + } + } /// /// The of the item. @@ -210,34 +389,12 @@ public ItemThrowSettings ThrowSettings /// /// Gets whether the item wrapper is allowed to be cached. /// - protected bool CanCache => !IsDestroyed && !IsPrefab && Serial != 0; - - /// - /// A private constructor to prevent external instantiation. - /// - /// The of the item. - protected Item(ItemBase itemBase) - { - Base = itemBase; - IsPrefab = InventoryItemLoader.TryGetItem(itemBase.ItemTypeId, out ItemBase prefab) && prefab == itemBase; - - if (CanCache) - { - Dictionary.Add(itemBase, this); - SerialsCache[itemBase.ItemSerial] = this; - } - } - - /// - /// An internal virtual method to signal to derived implementations to uncache when the base object is destroyed. - /// - internal virtual void OnRemove() - { - } + protected bool CanCache => !IsDestroyed && !IsPrefab && Serial != 0 && Base.isActiveAndEnabled; /// - /// Drops this item from player's inventory + /// Drops this item from player's inventory. /// + /// The dropped item as a . public Pickup DropItem() => Pickup.Get(Base.ServerDropItem(true)); /// @@ -253,146 +410,9 @@ public override string ToString() } /// - /// Gets the item wrapper from the or creates a new one if it doesn't exist and the provided was not null. - /// - /// The of the item. - /// The requested item or null. - [return: NotNullIfNotNull(nameof(itemBase))] - public static Item? Get(ItemBase? itemBase) - { - if (itemBase == null) - return null; - - return Dictionary.TryGetValue(itemBase, out Item item) ? item : CreateItemWrapper(itemBase); - } - - /// - /// Tries to get the item wrapper from the . - /// - /// The of the item. - /// The requested item. - /// True if the item exists, otherwise false. - public static bool TryGet(ItemBase? itemBase, [NotNullWhen(true)] out Item? item) - { - item = Get(itemBase); - return item != null; - } - - /// - /// Gets the item wrapper or null from . - /// - /// Serial of the item. - /// The requested item. - public static Item? Get(ushort serial) => TryGet(serial, out Item? item) ? item : null; - - /// - /// Gets the item wrapper or null from the based on provided serial number. - /// - /// The serial number of the item. - /// The requested item. - /// Whether the was successfully retrieved, otherwise false. - public static bool TryGet(ushort serial, [NotNullWhen(true)] out Item? item) - { - item = null; - if (SerialsCache.TryGetValue(serial, out item)) - return true; - - item = List.FirstOrDefault(x => x.Serial == serial); - if (item == null) - return false; - - SerialsCache[serial] = item; - return true; - } - - /// - /// Gets a pooled list of items having the same . - /// - /// Target type. - /// A List of items. - public static List GetAll(ItemType type) - { - List list = ListPool.Shared.Rent(); - list.AddRange(List.Where(n => n.Type == type)); - return list; - } - - /// - /// Gets a pooled list of items having the same . - /// - /// Target category. - /// A List of items. - public static List GetAll(ItemCategory category) - { - List list = ListPool.Shared.Rent(); - list.AddRange(List.Where(n => n.Category == category)); - return list; - } - - /// - /// Creates a new wrapper from the base item object. - /// - /// The base object. - /// The newly created wrapper. - protected static Item CreateItemWrapper(ItemBase item) - { - Type targetType = item.GetType(); - if (!typeWrappers.TryGetValue(targetType, out Func ctorFunc)) - { -#if DEBUG - Logger.Warn($"Unable to find LabApi wrapper for {nameof(Item)} {targetType.Name}, backup up to base constructor!"); -#endif - return new Item(item); - } - - return ctorFunc.Invoke(item); - } - - /// - /// A private method to handle the creation of new items in the server. - /// - /// The created instance. - private static void AddItem(ItemBase item) - { - try - { - if (!Dictionary.ContainsKey(item)) - _ = CreateItemWrapper(item); - } - catch(Exception e) - { - Console.Logger.InternalError($"Failed to handle item creation with error: {e}"); - } - } - - /// - /// A private method to handle the removal of items from the server. - /// - /// The to be destroyed instance. - private static void RemoveItem(ItemBase itemBase) - { - try - { - SerialsCache.Remove(itemBase.ItemSerial); - if (Dictionary.TryGetValue(itemBase, out Item item)) - { - Dictionary.Remove(itemBase); - item.OnRemove(); - } - } - catch(Exception e) - { - Console.Logger.InternalError($"Failed to handle item destruction with error: {e}"); - } - } - - /// - /// A private method to handle the addition of wrapper handlers. + /// An internal virtual method to signal to derived implementations to uncache when the base object is destroyed. /// - /// The derived base game type to handle. - /// A handler to construct the wrapper with the base game instance. - private static void Register(Func constructor) where T : ItemBase + internal virtual void OnRemove() { - typeWrappers.Add(typeof(T), x => constructor((T)x)); } } \ No newline at end of file diff --git a/LabApi/Features/Wrappers/Items/JailbirdItem.cs b/LabApi/Features/Wrappers/Items/JailbirdItem.cs index b7e5daf2..f5248e2f 100644 --- a/LabApi/Features/Wrappers/Items/JailbirdItem.cs +++ b/LabApi/Features/Wrappers/Items/JailbirdItem.cs @@ -1,4 +1,5 @@ -using System.Collections.Generic; +using InventorySystem.Items.Jailbird; +using System.Collections.Generic; using System.Diagnostics.CodeAnalysis; using BaseJailbirdItem = InventorySystem.Items.Jailbird.JailbirdItem; @@ -12,12 +13,28 @@ public class JailbirdItem : Item /// /// Contains all the cached jailbird items, accessible through their . /// - public new static Dictionary Dictionary { get; } = []; + public static new Dictionary Dictionary { get; } = []; /// /// A reference to all instances of . /// - public new static IReadOnlyCollection List => Dictionary.Values; + public static new IReadOnlyCollection List => Dictionary.Values; + + /// + /// Gets the jailbird item wrapper from the or creates a new one if it doesn't exist and the provided was not null. + /// + /// The of the item. + /// The requested item or null. + [return: NotNullIfNotNull(nameof(baseJailbirdItem))] + public static JailbirdItem? Get(BaseJailbirdItem? baseJailbirdItem) + { + if (baseJailbirdItem == null) + { + return null; + } + + return Dictionary.TryGetValue(baseJailbirdItem, out JailbirdItem item) ? item : (JailbirdItem)CreateItemWrapper(baseJailbirdItem); + } /// /// An internal constructor to prevent external instantiation. @@ -29,22 +46,20 @@ internal JailbirdItem(BaseJailbirdItem baseJailbirdItem) Base = baseJailbirdItem; if (CanCache) + { Dictionary.Add(baseJailbirdItem, this); + } } /// - /// An internal method to remove itself from the cache when the base object is destroyed. + /// The base object. /// - internal override void OnRemove() - { - base.OnRemove(); - Dictionary.Remove(Base); - } + public new BaseJailbirdItem Base { get; } /// - /// The base object. + /// Gets the current . /// - public new BaseJailbirdItem Base { get; } + public JailbirdWearState WearState => JailbirdDeteriorationTracker.ReceivedStates.GetValueOrDefault(Serial, JailbirdWearState.Healthy); /// /// Gets the number of charges performed. @@ -57,16 +72,16 @@ internal override void OnRemove() public bool IsCharging => Base.MovementOverrideActive; /// - /// Gets the jailbird item wrapper from the or creates a new one if it doesn't exist and the provided was not null. + /// Resets charges and damage dealt. /// - /// The of the item. - /// The requested item or null. - [return: NotNullIfNotNull(nameof(baseJailbirdItem))] - public static JailbirdItem? Get(BaseJailbirdItem? baseJailbirdItem) - { - if (baseJailbirdItem == null) - return null; + public void Reset() => Base.ServerReset(); - return Dictionary.TryGetValue(baseJailbirdItem, out JailbirdItem item) ? item : (JailbirdItem)CreateItemWrapper(baseJailbirdItem); + /// + /// An internal method to remove itself from the cache when the base object is destroyed. + /// + internal override void OnRemove() + { + base.OnRemove(); + Dictionary.Remove(Base); } } diff --git a/LabApi/Features/Wrappers/Items/KeycardItem.cs b/LabApi/Features/Wrappers/Items/KeycardItem.cs index f6ba7f73..3c74fc4b 100644 --- a/LabApi/Features/Wrappers/Items/KeycardItem.cs +++ b/LabApi/Features/Wrappers/Items/KeycardItem.cs @@ -17,49 +17,12 @@ public class KeycardItem : Item /// /// Contains all the cached keycard items, accessible through their . /// - public new static Dictionary Dictionary { get; } = []; + public static new Dictionary Dictionary { get; } = []; /// /// A reference to all instances of . /// - public new static IReadOnlyCollection List => Dictionary.Values; - - /// - /// An internal constructor to prevent external instantiation. - /// - /// The base object. - internal KeycardItem(BaseKeycardItem baseKeycardItem) - : base(baseKeycardItem) - { - Base = baseKeycardItem; - - if (CanCache) - Dictionary.Add(baseKeycardItem, this); - } - - /// - /// An internal method to remove itself from the cache when the base object is destroyed. - /// - internal override void OnRemove() - { - base.OnRemove(); - Dictionary.Remove(Base); - } - - /// - /// The base object. - /// - public new BaseKeycardItem Base { get; } - - /// - /// Gets the of the keycard. - /// - public DoorPermissionFlags Permissions => Base.GetPermissions(null); - - /// - /// Gets the of the keycard which represent the tiers shown on the keycard. - /// - public KeycardLevels Levels => new KeycardLevels(Permissions); + public static new IReadOnlyCollection List => Dictionary.Values; #region Custom Keycards @@ -136,19 +99,27 @@ internal override void OnRemove() public static KeycardItem? CreateCustomCard(ItemType itemType, Player targetPlayer, params object[] args) { if (targetPlayer == null) + { return null; + } if (!itemType.TryGetTemplate(out BaseKeycardItem template)) + { throw new ArgumentException($"Template for {nameof(itemType)} not found"); + } if (!template.Customizable) + { return null; + } int index = 0; foreach (DetailBase detailBase in template.Details) { if (detailBase is not ICustomizableDetail customizableDetail) + { continue; + } customizableDetail.SetArguments(new ArraySegment(args, index, customizableDetail.CustomizablePropertiesAmount)); index += customizableDetail.CustomizablePropertiesAmount; @@ -168,8 +139,49 @@ internal override void OnRemove() public static KeycardItem? Get(BaseKeycardItem? baseKeycardItem) { if (baseKeycardItem == null) + { return null; + } return Dictionary.TryGetValue(baseKeycardItem, out KeycardItem item) ? item : (KeycardItem)CreateItemWrapper(baseKeycardItem); } + + /// + /// An internal constructor to prevent external instantiation. + /// + /// The base object. + internal KeycardItem(BaseKeycardItem baseKeycardItem) + : base(baseKeycardItem) + { + Base = baseKeycardItem; + + if (CanCache) + { + Dictionary.Add(baseKeycardItem, this); + } + } + + /// + /// The base object. + /// + public new BaseKeycardItem Base { get; } + + /// + /// Gets the of the keycard. + /// + public DoorPermissionFlags Permissions => Base.GetPermissions(null); + + /// + /// Gets the of the keycard which represent the tiers shown on the keycard. + /// + public KeycardLevels Levels => new(Permissions); + + /// + /// An internal method to remove itself from the cache when the base object is destroyed. + /// + internal override void OnRemove() + { + base.OnRemove(); + Dictionary.Remove(Base); + } } diff --git a/LabApi/Features/Wrappers/Items/Light/FlashlightItem.cs b/LabApi/Features/Wrappers/Items/Light/FlashlightItem.cs index 87d660ae..8e3a83af 100644 --- a/LabApi/Features/Wrappers/Items/Light/FlashlightItem.cs +++ b/LabApi/Features/Wrappers/Items/Light/FlashlightItem.cs @@ -12,12 +12,28 @@ public class FlashlightItem : LightItem /// /// Contains all the cached flashlight items, accessible through their . /// - public new static Dictionary Dictionary { get; } = []; + public static new Dictionary Dictionary { get; } = []; /// /// A reference to all instances of . /// - public new static IReadOnlyCollection List => Dictionary.Values; + public static new IReadOnlyCollection List => Dictionary.Values; + + /// + /// Gets the flashlight item wrapper from the or creates a new one if it doesn't exist and the provided was not null. + /// + /// The of the item. + /// The requested item or null. + [return: NotNullIfNotNull(nameof(baseFlashlightItem))] + public static FlashlightItem? Get(BaseFlashlightItem? baseFlashlightItem) + { + if (baseFlashlightItem == null) + { + return null; + } + + return Dictionary.TryGetValue(baseFlashlightItem, out FlashlightItem item) ? item : (FlashlightItem)CreateItemWrapper(baseFlashlightItem); + } /// /// An internal constructor to prevent external instantiation. @@ -29,16 +45,9 @@ internal FlashlightItem(BaseFlashlightItem baseFlashlightItem) Base = baseFlashlightItem; if (CanCache) + { Dictionary.Add(baseFlashlightItem, this); - } - - /// - /// An internal method to remove itself from the cache when the base object is destroyed. - /// - internal override void OnRemove() - { - base.OnRemove(); - Dictionary.Remove(Base); + } } /// @@ -47,16 +56,11 @@ internal override void OnRemove() public new BaseFlashlightItem Base { get; } /// - /// Gets the flashlight item wrapper from the or creates a new one if it doesn't exist and the provided was not null. + /// An internal method to remove itself from the cache when the base object is destroyed. /// - /// The of the item. - /// The requested item or null. - [return: NotNullIfNotNull(nameof(baseFlashlightItem))] - public static FlashlightItem? Get(BaseFlashlightItem? baseFlashlightItem) + internal override void OnRemove() { - if (baseFlashlightItem == null) - return null; - - return Dictionary.TryGetValue(baseFlashlightItem, out FlashlightItem item) ? item : (FlashlightItem)CreateItemWrapper(baseFlashlightItem); + base.OnRemove(); + Dictionary.Remove(Base); } } diff --git a/LabApi/Features/Wrappers/Items/Light/LanternItem.cs b/LabApi/Features/Wrappers/Items/Light/LanternItem.cs index 81836e53..396ba16d 100644 --- a/LabApi/Features/Wrappers/Items/Light/LanternItem.cs +++ b/LabApi/Features/Wrappers/Items/Light/LanternItem.cs @@ -12,12 +12,28 @@ public class LanternItem : LightItem /// /// Contains all the cached lantern items, accessible through their . /// - public new static Dictionary Dictionary { get; } = []; + public static new Dictionary Dictionary { get; } = []; /// /// A reference to all instances of . /// - public new static IReadOnlyCollection List => Dictionary.Values; + public static new IReadOnlyCollection List => Dictionary.Values; + + /// + /// Gets the lantern item wrapper from the or creates a new one if it doesn't exist and the provided was not null. + /// + /// The of the item. + /// The requested item or null. + [return: NotNullIfNotNull(nameof(baseLanternItem))] + public static LanternItem? Get(BaseLanternItem? baseLanternItem) + { + if (baseLanternItem == null) + { + return null; + } + + return Dictionary.TryGetValue(baseLanternItem, out LanternItem item) ? item : (LanternItem)CreateItemWrapper(baseLanternItem); + } /// /// An internal constructor to prevent external instantiation. @@ -29,16 +45,9 @@ internal LanternItem(BaseLanternItem baseLanternItem) Base = baseLanternItem; if (CanCache) + { Dictionary.Add(baseLanternItem, this); - } - - /// - /// An internal method to remove itself from the cache when the base object is destroyed. - /// - internal override void OnRemove() - { - base.OnRemove(); - Dictionary.Remove(Base); + } } /// @@ -47,16 +56,11 @@ internal override void OnRemove() public new BaseLanternItem Base { get; } /// - /// Gets the lantern item wrapper from the or creates a new one if it doesn't exist and the provided was not null. + /// An internal method to remove itself from the cache when the base object is destroyed. /// - /// The of the item. - /// The requested item or null. - [return: NotNullIfNotNull(nameof(baseLanternItem))] - public static LanternItem? Get(BaseLanternItem? baseLanternItem) + internal override void OnRemove() { - if (baseLanternItem == null) - return null; - - return Dictionary.TryGetValue(baseLanternItem, out LanternItem item) ? item : (LanternItem)CreateItemWrapper(baseLanternItem); + base.OnRemove(); + Dictionary.Remove(Base); } } diff --git a/LabApi/Features/Wrappers/Items/Light/LightItem.cs b/LabApi/Features/Wrappers/Items/Light/LightItem.cs index b23d768a..13279be2 100644 --- a/LabApi/Features/Wrappers/Items/Light/LightItem.cs +++ b/LabApi/Features/Wrappers/Items/Light/LightItem.cs @@ -13,12 +13,28 @@ public class LightItem : Item /// /// Contains all the cached light items, accessible through their . /// - public new static Dictionary Dictionary { get; } = []; + public static new Dictionary Dictionary { get; } = []; /// /// A reference to all instances of . /// - public new static IReadOnlyCollection List => Dictionary.Values; + public static new IReadOnlyCollection List => Dictionary.Values; + + /// + /// Gets the light item wrapper from the or creates a new one if it doesn't exist and the provided was not null. + /// + /// The of the item. + /// The requested item or null. + [return: NotNullIfNotNull(nameof(toggleableLight))] + public static LightItem? Get(ToggleableLightItemBase? toggleableLight) + { + if (toggleableLight == null) + { + return null; + } + + return Dictionary.TryGetValue(toggleableLight, out LightItem item) ? item : (LightItem)CreateItemWrapper(toggleableLight); + } /// /// An internal constructor to prevent external instantiation. @@ -30,16 +46,9 @@ internal LightItem(ToggleableLightItemBase toggleableLightItemBase) Base = toggleableLightItemBase; if (CanCache) + { Dictionary.Add(toggleableLightItemBase, this); - } - - /// - /// An internal method to remove itself from the cache when the base object is destroyed. - /// - internal override void OnRemove() - { - base.OnRemove(); - Dictionary.Remove(Base); + } } /// @@ -61,16 +70,11 @@ public bool IsEmitting } /// - /// Gets the light item wrapper from the or creates a new one if it doesn't exist and the provided was not null. + /// An internal method to remove itself from the cache when the base object is destroyed. /// - /// The of the item. - /// The requested item or null. - [return: NotNullIfNotNull(nameof(toggleableLight))] - public static LightItem? Get(ToggleableLightItemBase? toggleableLight) + internal override void OnRemove() { - if (toggleableLight == null) - return null; - - return Dictionary.TryGetValue(toggleableLight, out LightItem item) ? item : (LightItem)CreateItemWrapper(toggleableLight); + base.OnRemove(); + Dictionary.Remove(Base); } } diff --git a/LabApi/Features/Wrappers/Items/MarshmallowItem.cs b/LabApi/Features/Wrappers/Items/MarshmallowItem.cs new file mode 100644 index 00000000..90ad42e3 --- /dev/null +++ b/LabApi/Features/Wrappers/Items/MarshmallowItem.cs @@ -0,0 +1,66 @@ +using System.Collections.Generic; +using System.Diagnostics.CodeAnalysis; +using BaseMarshmallowItem = InventorySystem.Items.MarshmallowMan.MarshmallowItem; + +namespace LabApi.Features.Wrappers; + +/// +/// The wrapper representing . +/// +public class MarshmallowItem : Item +{ + /// + /// Contains all the cached Marshmallow items, accessible through their . + /// + public static new Dictionary Dictionary { get; } = []; + + /// + /// A reference to all instances of . + /// + public static new IReadOnlyCollection List => Dictionary.Values; + + /// + /// Gets the SCP-021J item wrapper from the or creates a new one if it doesn't exist and the provided was not null. + /// + /// The of the item. + /// The requested item or null. + [return: NotNullIfNotNull(nameof(baseMarshmallowItem))] + public static MarshmallowItem? Get(BaseMarshmallowItem? baseMarshmallowItem) + { + if (baseMarshmallowItem == null) + { + return null; + } + + return Dictionary.TryGetValue(baseMarshmallowItem, out MarshmallowItem item) ? item : (MarshmallowItem)CreateItemWrapper(baseMarshmallowItem); + } + + /// + /// An internal constructor to prevent external instantiation. + /// + /// The base object. + internal MarshmallowItem(BaseMarshmallowItem baseMarshmallowItem) + : base(baseMarshmallowItem) + { + Base = baseMarshmallowItem; + + if (CanCache) + { + Dictionary.Add(baseMarshmallowItem, this); + } + } + + /// + /// The base object. + /// + public new BaseMarshmallowItem Base { get; } + + /// + /// An internal method to remove itself from the cache when the base object is destroyed. + /// + internal override void OnRemove() + { + base.OnRemove(); + Dictionary.Remove(Base); + } +} diff --git a/LabApi/Features/Wrappers/Items/MicroHIDItem.cs b/LabApi/Features/Wrappers/Items/MicroHIDItem.cs index 862a5210..0afe1d0d 100644 --- a/LabApi/Features/Wrappers/Items/MicroHIDItem.cs +++ b/LabApi/Features/Wrappers/Items/MicroHIDItem.cs @@ -13,12 +13,28 @@ public class MicroHIDItem : Item /// /// Contains all the cached micro hid items, accessible through their . /// - public new static Dictionary Dictionary { get; } = []; + public static new Dictionary Dictionary { get; } = []; /// /// A reference to all instances of . /// - public new static IReadOnlyCollection List => Dictionary.Values; + public static new IReadOnlyCollection List => Dictionary.Values; + + /// + /// Gets the micro hid item wrapper from the or creates a new one if it doesn't exist and the provided was not null. + /// + /// The of the item. + /// The requested item or null. + [return: NotNullIfNotNull(nameof(baseMicroHIDItem))] + public static MicroHIDItem? Get(BaseMicroHIDItem? baseMicroHIDItem) + { + if (baseMicroHIDItem == null) + { + return null; + } + + return Dictionary.TryGetValue(baseMicroHIDItem, out MicroHIDItem item) ? item : (MicroHIDItem)CreateItemWrapper(baseMicroHIDItem); + } /// /// An internal constructor to prevent external instantiation. @@ -30,16 +46,9 @@ internal MicroHIDItem(BaseMicroHIDItem baseMicroHIDItem) Base = baseMicroHIDItem; if (CanCache) + { Dictionary.Add(baseMicroHIDItem, this); - } - - /// - /// An internal method to remove itself from the cache when the base object is destroyed. - /// - internal override void OnRemove() - { - base.OnRemove(); - Dictionary.Remove(Base); + } } /// @@ -130,19 +139,14 @@ public MicroHidFiringMode FiringMode /// /// The sounds range in meters. /// Returns true if the micro is emitting sound, otherwise false. - public bool TryGetSoundEmissionRange(out float range) => Base.ServerTryGetSoundEmissionRange(out range); + public bool TryGetSoundEmissionRange(out float range) => Base.TryGetSoundEmissionRange(out range); /// - /// Gets the micro hid item wrapper from the or creates a new one if it doesn't exist and the provided was not null. + /// An internal method to remove itself from the cache when the base object is destroyed. /// - /// The of the item. - /// The requested item or null. - [return: NotNullIfNotNull(nameof(baseMicroHIDItem))] - public static MicroHIDItem? Get(BaseMicroHIDItem? baseMicroHIDItem) + internal override void OnRemove() { - if (baseMicroHIDItem == null) - return null; - - return Dictionary.TryGetValue(baseMicroHIDItem, out MicroHIDItem item) ? item : (MicroHIDItem)CreateItemWrapper(baseMicroHIDItem); + base.OnRemove(); + Dictionary.Remove(Base); } } diff --git a/LabApi/Features/Wrappers/Items/RadioItem.cs b/LabApi/Features/Wrappers/Items/RadioItem.cs index 26b852bb..607de207 100644 --- a/LabApi/Features/Wrappers/Items/RadioItem.cs +++ b/LabApi/Features/Wrappers/Items/RadioItem.cs @@ -14,12 +14,28 @@ public class RadioItem : Item /// /// Contains all the cached radio items, accessible through their . /// - public new static Dictionary Dictionary { get; } = []; + public static new Dictionary Dictionary { get; } = []; /// /// A reference to all instances of . /// - public new static IReadOnlyCollection List => Dictionary.Values; + public static new IReadOnlyCollection List => Dictionary.Values; + + /// + /// Gets the radio item wrapper from the or creates a new one if it doesn't exist and the provided was not null. + /// + /// The of the item. + /// The requested item or null. + [return: NotNullIfNotNull(nameof(baseRadioItem))] + public static RadioItem? Get(BaseRadioItem? baseRadioItem) + { + if (baseRadioItem == null) + { + return null; + } + + return Dictionary.TryGetValue(baseRadioItem, out RadioItem item) ? item : (RadioItem)CreateItemWrapper(baseRadioItem); + } /// /// An internal constructor to prevent external instantiation. @@ -31,16 +47,9 @@ internal RadioItem(BaseRadioItem baseRadioItem) Base = baseRadioItem; if (CanCache) + { Dictionary.Add(baseRadioItem, this); - } - - /// - /// An internal method to remove itself from the cache when the base object is destroyed. - /// - internal override void OnRemove() - { - base.OnRemove(); - Dictionary.Remove(Base); + } } /// @@ -73,16 +82,11 @@ public byte BatteryPercent public RadioMessages.RadioRangeLevel RangeLevel => Base.RangeLevel; /// - /// Gets the radio item wrapper from the or creates a new one if it doesn't exist and the provided was not null. + /// An internal method to remove itself from the cache when the base object is destroyed. /// - /// The of the item. - /// The requested item or null. - [return: NotNullIfNotNull(nameof(baseRadioItem))] - public static RadioItem? Get(BaseRadioItem? baseRadioItem) + internal override void OnRemove() { - if (baseRadioItem == null) - return null; - - return Dictionary.TryGetValue(baseRadioItem, out RadioItem item) ? item : (RadioItem)CreateItemWrapper(baseRadioItem); + base.OnRemove(); + Dictionary.Remove(Base); } } diff --git a/LabApi/Features/Wrappers/Items/SnowballItem.cs b/LabApi/Features/Wrappers/Items/SnowballItem.cs new file mode 100644 index 00000000..7d452430 --- /dev/null +++ b/LabApi/Features/Wrappers/Items/SnowballItem.cs @@ -0,0 +1,65 @@ +using System.Collections.Generic; +using System.Diagnostics.CodeAnalysis; +using BaseSnowballItem = InventorySystem.Items.ThrowableProjectiles.SnowballItem; + +namespace LabApi.Features.Wrappers; + +/// +/// The wrapper representing . +/// +public class SnowballItem : ThrowableItem +{ + /// + /// Contains all the cached snowball items, accessible through their . + /// + public static new Dictionary Dictionary { get; } = []; + + /// + /// A reference to all instances of . + /// + public static new IReadOnlyCollection List => Dictionary.Values; + + /// + /// Gets the snowball item wrapper from the or creates a new one if it doesn't exist and the provided was not null. + /// + /// The of the item. + /// The requested item or null. + [return: NotNullIfNotNull(nameof(baseSnowballItem))] + public static SnowballItem? Get(BaseSnowballItem? baseSnowballItem) + { + if (baseSnowballItem == null) + { + return null; + } + + return Dictionary.TryGetValue(baseSnowballItem, out SnowballItem item) ? item : (SnowballItem)CreateItemWrapper(baseSnowballItem); + } + + /// + /// An internal constructor to prevent external instantiation. + /// + /// The base object. + internal SnowballItem(BaseSnowballItem baseThrowableItem) + : base(baseThrowableItem) + { + Base = baseThrowableItem; + + if (CanCache) + { + Dictionary.Add(baseThrowableItem, this); + } + } + + /// + /// The base object. + /// + public new BaseSnowballItem Base { get; } + + /// + internal override void OnRemove() + { + base.OnRemove(); + + Dictionary.Remove(Base); + } +} diff --git a/LabApi/Features/Wrappers/Items/ThrowableItem.cs b/LabApi/Features/Wrappers/Items/ThrowableItem.cs index 9d2a8f6f..c29a49fc 100644 --- a/LabApi/Features/Wrappers/Items/ThrowableItem.cs +++ b/LabApi/Features/Wrappers/Items/ThrowableItem.cs @@ -13,12 +13,28 @@ public class ThrowableItem : Item /// /// Contains all the cached throwable items, accessible through their . /// - public new static Dictionary Dictionary { get; } = []; + public static new Dictionary Dictionary { get; } = []; /// /// A reference to all instances of . /// - public new static IReadOnlyCollection List => Dictionary.Values; + public static new IReadOnlyCollection List => Dictionary.Values; + + /// + /// Gets the throwable item wrapper from the or creates a new one if it doesn't exist and the provided was not null. + /// + /// The of the item. + /// The requested item or null. + [return: NotNullIfNotNull(nameof(baseThrowableItem))] + public static ThrowableItem? Get(BaseThrowableItem? baseThrowableItem) + { + if (baseThrowableItem == null) + { + return null; + } + + return Dictionary.TryGetValue(baseThrowableItem, out ThrowableItem item) ? item : (ThrowableItem)CreateItemWrapper(baseThrowableItem); + } /// /// An internal constructor to prevent external instantiation. @@ -30,16 +46,9 @@ internal ThrowableItem(BaseThrowableItem baseThrowableItem) Base = baseThrowableItem; if (CanCache) + { Dictionary.Add(baseThrowableItem, this); - } - - /// - /// An internal method to remove itself from the cache when the base object is destroyed. - /// - internal override void OnRemove() - { - base.OnRemove(); - Dictionary.Remove(Base); + } } /// @@ -47,12 +56,12 @@ internal override void OnRemove() /// public new BaseThrowableItem Base { get; } - /// - /// The projectile prefab instance, changes to this will be reflect across all new spawned projectiles. - /// + ///// + ///// The projectile prefab instance, changes to this will be reflect across all new spawned projectiles. + ///// // TODO: use projectile wrapper. // FIX: prefab caching. - //Pickup ProjectilePrefab => Pickup.Get(Base.Projectile); + // Pickup ProjectilePrefab => Pickup.Get(Base.Projectile); /// /// Gets or set the velocity added in the forward direction on a weak throw. @@ -127,16 +136,11 @@ public Vector3 FullThrowRelativePosition } /// - /// Gets the throwable item wrapper from the or creates a new one if it doesn't exist and the provided was not null. + /// An internal method to remove itself from the cache when the base object is destroyed. /// - /// The of the item. - /// The requested item or null. - [return: NotNullIfNotNull(nameof(baseThrowableItem))] - public static ThrowableItem? Get(BaseThrowableItem? baseThrowableItem) + internal override void OnRemove() { - if (baseThrowableItem == null) - return null; - - return Dictionary.TryGetValue(baseThrowableItem, out ThrowableItem item) ? item : (ThrowableItem)CreateItemWrapper(baseThrowableItem); + base.OnRemove(); + Dictionary.Remove(Base); } } diff --git a/LabApi/Features/Wrappers/Items/Usable/Consumable/AdrenalineItem.cs b/LabApi/Features/Wrappers/Items/Usable/Consumable/AdrenalineItem.cs index 93b296fb..1df85413 100644 --- a/LabApi/Features/Wrappers/Items/Usable/Consumable/AdrenalineItem.cs +++ b/LabApi/Features/Wrappers/Items/Usable/Consumable/AdrenalineItem.cs @@ -12,12 +12,28 @@ public class AdrenalineItem : ConsumableItem /// /// Contains all the cached adrenaline items, accessible through their . /// - public new static Dictionary Dictionary { get; } = []; + public static new Dictionary Dictionary { get; } = []; /// /// A reference to all instances of . /// - public new static IReadOnlyCollection List => Dictionary.Values; + public static new IReadOnlyCollection List => Dictionary.Values; + + /// + /// Gets the adrenaline item wrapper from the or creates a new one if it doesn't exist and the provided was not null. + /// + /// The of the item. + /// The requested item or null. + [return: NotNullIfNotNull(nameof(adrenaline))] + public static AdrenalineItem? Get(Adrenaline? adrenaline) + { + if (adrenaline == null) + { + return null; + } + + return Dictionary.TryGetValue(adrenaline, out AdrenalineItem item) ? item : (AdrenalineItem)CreateItemWrapper(adrenaline); + } /// /// An internal constructor to prevent external instantiation. @@ -29,16 +45,9 @@ internal AdrenalineItem(Adrenaline adrenaline) Base = adrenaline; if (CanCache) + { Dictionary.Add(adrenaline, this); - } - - /// - /// An internal method to remove itself from the cache when the base object is destroyed. - /// - internal override void OnRemove() - { - base.OnRemove(); - Dictionary.Remove(Base); + } } /// @@ -47,16 +56,11 @@ internal override void OnRemove() public new Adrenaline Base { get; } /// - /// Gets the adrenaline item wrapper from the or creates a new one if it doesn't exist and the provided was not null. + /// An internal method to remove itself from the cache when the base object is destroyed. /// - /// The of the item. - /// The requested item or null. - [return: NotNullIfNotNull(nameof(adrenaline))] - public static AdrenalineItem? Get(Adrenaline? adrenaline) + internal override void OnRemove() { - if (adrenaline == null) - return null; - - return Dictionary.TryGetValue(adrenaline, out AdrenalineItem item) ? item : (AdrenalineItem)CreateItemWrapper(adrenaline); + base.OnRemove(); + Dictionary.Remove(Base); } } diff --git a/LabApi/Features/Wrappers/Items/Usable/Consumable/AntiScp207Item.cs b/LabApi/Features/Wrappers/Items/Usable/Consumable/AntiScp207Item.cs index 435b4500..87b3ff40 100644 --- a/LabApi/Features/Wrappers/Items/Usable/Consumable/AntiScp207Item.cs +++ b/LabApi/Features/Wrappers/Items/Usable/Consumable/AntiScp207Item.cs @@ -12,12 +12,28 @@ public class AntiScp207Item : ConsumableItem /// /// Contains all the cached anti SCP-207 items, accessible through their . /// - public new static Dictionary Dictionary { get; } = []; + public static new Dictionary Dictionary { get; } = []; /// /// A reference to all instances of . /// - public new static IReadOnlyCollection List => Dictionary.Values; + public static new IReadOnlyCollection List => Dictionary.Values; + + /// + /// Gets the anti SPC-207 item wrapper from the or creates a new one if it doesn't exist and the provided was not null. + /// + /// The of the item. + /// The requested item or null. + [return: NotNullIfNotNull(nameof(antiScp207))] + public static AntiScp207Item? Get(AntiScp207? antiScp207) + { + if (antiScp207 == null) + { + return null; + } + + return Dictionary.TryGetValue(antiScp207, out AntiScp207Item item) ? item : (AntiScp207Item)CreateItemWrapper(antiScp207); + } /// /// An internal constructor to prevent external instantiation. @@ -29,16 +45,9 @@ internal AntiScp207Item(AntiScp207 antiScp207) Base = antiScp207; if (CanCache) + { Dictionary.Add(antiScp207, this); - } - - /// - /// An internal method to remove itself from the cache when the base object is destroyed. - /// - internal override void OnRemove() - { - base.OnRemove(); - Dictionary.Remove(Base); + } } /// @@ -47,16 +56,11 @@ internal override void OnRemove() public new AntiScp207 Base { get; } /// - /// Gets the anti SPC-207 item wrapper from the or creates a new one if it doesn't exist and the provided was not null. + /// An internal method to remove itself from the cache when the base object is destroyed. /// - /// The of the item. - /// The requested item or null. - [return: NotNullIfNotNull(nameof(antiScp207))] - public static AntiScp207Item? Get(AntiScp207? antiScp207) + internal override void OnRemove() { - if (antiScp207 == null) - return null; - - return Dictionary.TryGetValue(antiScp207, out AntiScp207Item item) ? item : (AntiScp207Item)CreateItemWrapper(antiScp207); + base.OnRemove(); + Dictionary.Remove(Base); } } diff --git a/LabApi/Features/Wrappers/Items/Usable/Consumable/ConsumableItem.cs b/LabApi/Features/Wrappers/Items/Usable/Consumable/ConsumableItem.cs index b1e22781..6d7ac7a4 100644 --- a/LabApi/Features/Wrappers/Items/Usable/Consumable/ConsumableItem.cs +++ b/LabApi/Features/Wrappers/Items/Usable/Consumable/ConsumableItem.cs @@ -12,12 +12,28 @@ public class ConsumableItem : UsableItem /// /// Contains all the cached consumable items, accessible through their . /// - public new static Dictionary Dictionary { get; } = []; + public static new Dictionary Dictionary { get; } = []; /// /// A reference to all instances of . /// - public new static IReadOnlyCollection List => Dictionary.Values; + public static new IReadOnlyCollection List => Dictionary.Values; + + /// + /// Gets the consumable item wrapper from the or creates a new one if it doesn't exist and the provided was not null. + /// + /// The of the item. + /// The requested item or null. + [return: NotNullIfNotNull(nameof(consumable))] + public static ConsumableItem? Get(Consumable? consumable) + { + if (consumable == null) + { + return null; + } + + return Dictionary.TryGetValue(consumable, out ConsumableItem item) ? item : (ConsumableItem)CreateItemWrapper(consumable); + } /// /// An internal constructor to prevent external instantiation. @@ -29,16 +45,9 @@ internal ConsumableItem(Consumable consumable) Base = consumable; if (CanCache) + { Dictionary.Add(consumable, this); - } - - /// - /// An internal method to remove itself from the cache when the base object is destroyed. - /// - internal override void OnRemove() - { - base.OnRemove(); - Dictionary.Remove(Base); + } } /// @@ -47,16 +56,11 @@ internal override void OnRemove() public new Consumable Base { get; } /// - /// Gets the consumable item wrapper from the or creates a new one if it doesn't exist and the provided was not null. + /// An internal method to remove itself from the cache when the base object is destroyed. /// - /// The of the item. - /// The requested item or null. - [return: NotNullIfNotNull(nameof(consumable))] - public static ConsumableItem? Get(Consumable? consumable) + internal override void OnRemove() { - if (consumable == null) - return null; - - return Dictionary.TryGetValue(consumable, out ConsumableItem item) ? item : (ConsumableItem)CreateItemWrapper(consumable); + base.OnRemove(); + Dictionary.Remove(Base); } } diff --git a/LabApi/Features/Wrappers/Items/Usable/Consumable/MedkitItem.cs b/LabApi/Features/Wrappers/Items/Usable/Consumable/MedkitItem.cs index 01da404b..ae8743de 100644 --- a/LabApi/Features/Wrappers/Items/Usable/Consumable/MedkitItem.cs +++ b/LabApi/Features/Wrappers/Items/Usable/Consumable/MedkitItem.cs @@ -12,12 +12,28 @@ public class MedkitItem : ConsumableItem /// /// Contains all the cached medkit items, accessible through their . /// - public new static Dictionary Dictionary { get; } = []; + public static new Dictionary Dictionary { get; } = []; /// /// A reference to all instances of . /// - public new static IReadOnlyCollection List => Dictionary.Values; + public static new IReadOnlyCollection List => Dictionary.Values; + + /// + /// Gets the medkit item wrapper from the or creates a new one if it doesn't exist and the provided was not null. + /// + /// The of the item. + /// The requested item or null. + [return: NotNullIfNotNull(nameof(medkit))] + public static MedkitItem? Get(Medkit? medkit) + { + if (medkit == null) + { + return null; + } + + return Dictionary.TryGetValue(medkit, out MedkitItem item) ? item : (MedkitItem)CreateItemWrapper(medkit); + } /// /// An internal constructor to prevent external instantiation. @@ -29,16 +45,9 @@ internal MedkitItem(Medkit medkit) Base = medkit; if (CanCache) + { Dictionary.Add(medkit, this); - } - - /// - /// An internal method to remove itself from the cache when the base object is destroyed. - /// - internal override void OnRemove() - { - base.OnRemove(); - Dictionary.Remove(Base); + } } /// @@ -47,16 +56,11 @@ internal override void OnRemove() public new Medkit Base { get; } /// - /// Gets the medkit item wrapper from the or creates a new one if it doesn't exist and the provided was not null. + /// An internal method to remove itself from the cache when the base object is destroyed. /// - /// The of the item. - /// The requested item or null. - [return: NotNullIfNotNull(nameof(medkit))] - public static MedkitItem? Get(Medkit? medkit) + internal override void OnRemove() { - if (medkit == null) - return null; - - return Dictionary.TryGetValue(medkit, out MedkitItem item) ? item : (MedkitItem)CreateItemWrapper(medkit); + base.OnRemove(); + Dictionary.Remove(Base); } } diff --git a/LabApi/Features/Wrappers/Items/Usable/Consumable/PainkillersItem.cs b/LabApi/Features/Wrappers/Items/Usable/Consumable/PainkillersItem.cs index c02db914..cb37dcd9 100644 --- a/LabApi/Features/Wrappers/Items/Usable/Consumable/PainkillersItem.cs +++ b/LabApi/Features/Wrappers/Items/Usable/Consumable/PainkillersItem.cs @@ -12,12 +12,28 @@ public class PainkillersItem : ConsumableItem /// /// Contains all the cached painkiller items, accessible through their . /// - public new static Dictionary Dictionary { get; } = []; + public static new Dictionary Dictionary { get; } = []; /// /// A reference to all instances of . /// - public new static IReadOnlyCollection List => Dictionary.Values; + public static new IReadOnlyCollection List => Dictionary.Values; + + /// + /// Gets the painkillers item wrapper from the or creates a new one if it doesn't exist and the provided was not null. + /// + /// The of the item. + /// The requested item or null. + [return: NotNullIfNotNull(nameof(painkillers))] + public static PainkillersItem? Get(Painkillers? painkillers) + { + if (painkillers == null) + { + return null; + } + + return Dictionary.TryGetValue(painkillers, out PainkillersItem item) ? item : (PainkillersItem)CreateItemWrapper(painkillers); + } /// /// An internal constructor to prevent external instantiation. @@ -29,16 +45,9 @@ internal PainkillersItem(Painkillers painkillers) Base = painkillers; if (CanCache) + { Dictionary.Add(painkillers, this); - } - - /// - /// An internal method to remove itself from the cache when the base object is destroyed. - /// - internal override void OnRemove() - { - base.OnRemove(); - Dictionary.Remove(Base); + } } /// @@ -47,16 +56,11 @@ internal override void OnRemove() public new Painkillers Base { get; } /// - /// Gets the painkillers item wrapper from the or creates a new one if it doesn't exist and the provided was not null. + /// An internal method to remove itself from the cache when the base object is destroyed. /// - /// The of the item. - /// The requested item or null. - [return: NotNullIfNotNull(nameof(painkillers))] - public static PainkillersItem? Get(Painkillers? painkillers) + internal override void OnRemove() { - if (painkillers == null) - return null; - - return Dictionary.TryGetValue(painkillers, out PainkillersItem item) ? item : (PainkillersItem)CreateItemWrapper(painkillers); + base.OnRemove(); + Dictionary.Remove(Base); } } diff --git a/LabApi/Features/Wrappers/Items/Usable/Consumable/Scp021JItem.cs b/LabApi/Features/Wrappers/Items/Usable/Consumable/Scp021JItem.cs new file mode 100644 index 00000000..73dd2a3d --- /dev/null +++ b/LabApi/Features/Wrappers/Items/Usable/Consumable/Scp021JItem.cs @@ -0,0 +1,66 @@ +using System.Collections.Generic; +using System.Diagnostics.CodeAnalysis; +using BaseScp021JItem = InventorySystem.Items.Usables.Scp021J; + +namespace LabApi.Features.Wrappers; + +/// +/// The wrapper representing . +/// +public class Scp021JItem : ConsumableItem +{ + /// + /// Contains all the cached SCP-021J items, accessible through their . + /// + public static new Dictionary Dictionary { get; } = []; + + /// + /// A reference to all instances of . + /// + public static new IReadOnlyCollection List => Dictionary.Values; + + /// + /// Gets the SCP-021J item wrapper from the or creates a new one if it doesn't exist and the provided was not null. + /// + /// The of the item. + /// The requested item or null. + [return: NotNullIfNotNull(nameof(baseScp021JItem))] + public static Scp021JItem? Get(BaseScp021JItem? baseScp021JItem) + { + if (baseScp021JItem == null) + { + return null; + } + + return Dictionary.TryGetValue(baseScp021JItem, out Scp021JItem item) ? item : (Scp021JItem)CreateItemWrapper(baseScp021JItem); + } + + /// + /// An internal constructor to prevent external instantiation. + /// + /// The base object. + internal Scp021JItem(BaseScp021JItem baseScp021JItem) + : base(baseScp021JItem) + { + Base = baseScp021JItem; + + if (CanCache) + { + Dictionary.Add(baseScp021JItem, this); + } + } + + /// + /// The base object. + /// + public new BaseScp021JItem Base { get; } + + /// + /// An internal method to remove itself from the cache when the base object is destroyed. + /// + internal override void OnRemove() + { + base.OnRemove(); + Dictionary.Remove(Base); + } +} diff --git a/LabApi/Features/Wrappers/Items/Usable/Consumable/Scp1853Item.cs b/LabApi/Features/Wrappers/Items/Usable/Consumable/Scp1853Item.cs index 05de4a56..bc270187 100644 --- a/LabApi/Features/Wrappers/Items/Usable/Consumable/Scp1853Item.cs +++ b/LabApi/Features/Wrappers/Items/Usable/Consumable/Scp1853Item.cs @@ -12,12 +12,28 @@ public class Scp1853Item : ConsumableItem /// /// Contains all the cached SCP-1853 items, accessible through their . /// - public new static Dictionary Dictionary { get; } = []; + public static new Dictionary Dictionary { get; } = []; /// /// A reference to all instances of . /// - public new static IReadOnlyCollection List => Dictionary.Values; + public static new IReadOnlyCollection List => Dictionary.Values; + + /// + /// Gets the SCP-1853 item wrapper from the or creates a new one if it doesn't exist and the provided was not null. + /// + /// The of the item. + /// The requested item or null. + [return: NotNullIfNotNull(nameof(baseScp1853Item))] + public static Scp1853Item? Get(BaseScp1853Item? baseScp1853Item) + { + if (baseScp1853Item == null) + { + return null; + } + + return Dictionary.TryGetValue(baseScp1853Item, out Scp1853Item item) ? item : (Scp1853Item)CreateItemWrapper(baseScp1853Item); + } /// /// An internal constructor to prevent external instantiation. @@ -29,16 +45,9 @@ internal Scp1853Item(BaseScp1853Item baseScp1853Item) Base = baseScp1853Item; if (CanCache) + { Dictionary.Add(baseScp1853Item, this); - } - - /// - /// An internal method to remove itself from the cache when the base object is destroyed. - /// - internal override void OnRemove() - { - base.OnRemove(); - Dictionary.Remove(Base); + } } /// @@ -47,16 +56,11 @@ internal override void OnRemove() public new BaseScp1853Item Base { get; } /// - /// Gets the SCP-1853 item wrapper from the or creates a new one if it doesn't exist and the provided was not null. + /// An internal method to remove itself from the cache when the base object is destroyed. /// - /// The of the item. - /// The requested item or null. - [return: NotNullIfNotNull(nameof(baseScp1853Item))] - public static Scp1853Item? Get(BaseScp1853Item? baseScp1853Item) + internal override void OnRemove() { - if (baseScp1853Item == null) - return null; - - return Dictionary.TryGetValue(baseScp1853Item, out Scp1853Item item) ? item : (Scp1853Item)CreateItemWrapper(baseScp1853Item); + base.OnRemove(); + Dictionary.Remove(Base); } } diff --git a/LabApi/Features/Wrappers/Items/Usable/Consumable/Scp207Item.cs b/LabApi/Features/Wrappers/Items/Usable/Consumable/Scp207Item.cs index ed5fa481..779cfe2d 100644 --- a/LabApi/Features/Wrappers/Items/Usable/Consumable/Scp207Item.cs +++ b/LabApi/Features/Wrappers/Items/Usable/Consumable/Scp207Item.cs @@ -12,12 +12,28 @@ public class Scp207Item : ConsumableItem /// /// Contains all the cached SCP-207 items, accessible through their . /// - public new static Dictionary Dictionary { get; } = []; + public static new Dictionary Dictionary { get; } = []; /// /// A reference to all instances of . /// - public new static IReadOnlyCollection List => Dictionary.Values; + public static new IReadOnlyCollection List => Dictionary.Values; + + /// + /// Gets the SCP-207 item wrapper from the or creates a new one if it doesn't exist and the provided was not null. + /// + /// The of the item. + /// The requested item or null. + [return: NotNullIfNotNull(nameof(scp207))] + public static Scp207Item? Get(Scp207? scp207) + { + if (scp207 == null) + { + return null; + } + + return Dictionary.TryGetValue(scp207, out Scp207Item item) ? item : (Scp207Item)CreateItemWrapper(scp207); + } /// /// An internal constructor to prevent external instantiation. @@ -29,16 +45,9 @@ internal Scp207Item(Scp207 scp207) Base = scp207; if (CanCache) + { Dictionary.Add(scp207, this); - } - - /// - /// An internal method to remove itself from the cache when the base object is destroyed. - /// - internal override void OnRemove() - { - base.OnRemove(); - Dictionary.Remove(Base); + } } /// @@ -47,16 +56,11 @@ internal override void OnRemove() public new Scp207 Base { get; } /// - /// Gets the SCP-207 item wrapper from the or creates a new one if it doesn't exist and the provided was not null. + /// An internal method to remove itself from the cache when the base object is destroyed. /// - /// The of the item. - /// The requested item or null. - [return: NotNullIfNotNull(nameof(scp207))] - public static Scp207Item? Get(Scp207? scp207) + internal override void OnRemove() { - if (scp207 == null) - return null; - - return Dictionary.TryGetValue(scp207, out Scp207Item item) ? item : (Scp207Item)CreateItemWrapper(scp207); + base.OnRemove(); + Dictionary.Remove(Base); } } diff --git a/LabApi/Features/Wrappers/Items/Usable/Consumable/Scp500Item.cs b/LabApi/Features/Wrappers/Items/Usable/Consumable/Scp500Item.cs index 764350c8..be772060 100644 --- a/LabApi/Features/Wrappers/Items/Usable/Consumable/Scp500Item.cs +++ b/LabApi/Features/Wrappers/Items/Usable/Consumable/Scp500Item.cs @@ -12,12 +12,28 @@ public class Scp500Item : ConsumableItem /// /// Contains all the cached SCP-500 items, accessible through their . /// - public new static Dictionary Dictionary { get; } = []; + public static new Dictionary Dictionary { get; } = []; /// /// A reference to all instances of . /// - public new static IReadOnlyCollection List => Dictionary.Values; + public static new IReadOnlyCollection List => Dictionary.Values; + + /// + /// Gets the SCP-500 item wrapper from the or creates a new one if it doesn't exist and the provided was not null. + /// + /// The of the item. + /// The requested item or null. + [return: NotNullIfNotNull(nameof(scp500))] + public static Scp500Item? Get(Scp500? scp500) + { + if (scp500 == null) + { + return null; + } + + return Dictionary.TryGetValue(scp500, out Scp500Item item) ? item : (Scp500Item)CreateItemWrapper(scp500); + } /// /// An internal constructor to prevent external instantiation. @@ -29,16 +45,9 @@ internal Scp500Item(Scp500 scp500) Base = scp500; if (CanCache) + { Dictionary.Add(scp500, this); - } - - /// - /// An internal method to remove itself from the cache when the base object is destroyed. - /// - internal override void OnRemove() - { - base.OnRemove(); - Dictionary.Remove(Base); + } } /// @@ -47,16 +56,11 @@ internal override void OnRemove() public new Scp500 Base { get; } /// - /// Gets the SCP-500 item wrapper from the or creates a new one if it doesn't exist and the provided was not null. + /// An internal method to remove itself from the cache when the base object is destroyed. /// - /// The of the item. - /// The requested item or null. - [return: NotNullIfNotNull(nameof(scp500))] - public static Scp500Item? Get(Scp500? scp500) + internal override void OnRemove() { - if (scp500 == null) - return null; - - return Dictionary.TryGetValue(scp500, out Scp500Item item) ? item : (Scp500Item)CreateItemWrapper(scp500); + base.OnRemove(); + Dictionary.Remove(Base); } } diff --git a/LabApi/Features/Wrappers/Items/Usable/Scp1344Item.cs b/LabApi/Features/Wrappers/Items/Usable/Scp1344Item.cs index b9289d48..288283df 100644 --- a/LabApi/Features/Wrappers/Items/Usable/Scp1344Item.cs +++ b/LabApi/Features/Wrappers/Items/Usable/Scp1344Item.cs @@ -14,12 +14,43 @@ public class Scp1344Item : UsableItem /// /// Contains all the cached SCP-1344 items, accessible through their . /// - public new static Dictionary Dictionary { get; } = []; + public static new Dictionary Dictionary { get; } = []; /// /// A reference to all instances of . /// - public new static IReadOnlyCollection List => Dictionary.Values; + public static new IReadOnlyCollection List => Dictionary.Values; + + /// + /// Gets the SCP-1576 item wrapper from the or creates a new one if it doesn't exist and the provided was not null. + /// + /// The of the item. + /// The requested item or null. + [return: NotNullIfNotNull(nameof(baseItem))] + public static Scp1344Item? Get(BaseScp1344Item? baseItem) + { + if (baseItem == null) + { + return null; + } + + return Dictionary.TryGetValue(baseItem, out Scp1344Item item) ? item : (Scp1344Item)CreateItemWrapper(baseItem); + } + + /// + /// An internal constructor to prevent external instantiation. + /// + /// The base object. + internal Scp1344Item(BaseScp1344Item baseItem) + : base(baseItem) + { + Base = baseItem; + + if (CanCache) + { + Dictionary.Add(baseItem, this); + } + } /// /// The base object. @@ -58,32 +89,6 @@ public Scp1344Status Status /// public SeveredEyes SeveredEyesEffect => Base.SeveredEyesEffect; - /// - /// An internal constructor to prevent external instantiation. - /// - /// The base object. - internal Scp1344Item(BaseScp1344Item baseItem) : base(baseItem) - { - Base = baseItem; - - if (CanCache) - Dictionary.Add(baseItem, this); - } - - /// - /// Gets the SCP-1576 item wrapper from the or creates a new one if it doesn't exist and the provided was not null. - /// - /// The of the item. - /// The requested item or null. - [return: NotNullIfNotNull(nameof(baseItem))] - public static Scp1344Item? Get(BaseScp1344Item? baseItem) - { - if (baseItem == null) - return null; - - return Dictionary.TryGetValue(baseItem, out Scp1344Item item) ? item : (Scp1344Item)CreateItemWrapper(baseItem); - } - /// /// An internal method to remove itself from the cache when the base object is destroyed. /// diff --git a/LabApi/Features/Wrappers/Items/Usable/Scp1576Item.cs b/LabApi/Features/Wrappers/Items/Usable/Scp1576Item.cs index 61b5a49a..e93114a4 100644 --- a/LabApi/Features/Wrappers/Items/Usable/Scp1576Item.cs +++ b/LabApi/Features/Wrappers/Items/Usable/Scp1576Item.cs @@ -1,4 +1,5 @@ -using System.Collections.Generic; +using CustomPlayerEffects; +using System.Collections.Generic; using System.Diagnostics.CodeAnalysis; using System.Linq; using BaseScp1576Item = InventorySystem.Items.Usables.Scp1576.Scp1576Item; @@ -13,17 +14,17 @@ public class Scp1576Item : UsableItem /// /// Contains all the cached SCP-1576 items, accessible through their . /// - public new static Dictionary Dictionary { get; } = []; + public static new Dictionary Dictionary { get; } = []; /// /// A reference to all instances of . /// - public new static IReadOnlyCollection List => Dictionary.Values; + public static new IReadOnlyCollection List => Dictionary.Values; /// /// The set of players who are able to transmit their voice to spectators using Scp1576. /// - public static IEnumerable TransmitterList => BaseScp1576Item.ValidatedTransmitters.Select(x => Player.Get(x)); + public static IEnumerable TransmitterList => Player.List.Where(player => player.HasEffect()); /// /// The set of players who are able to receive hear spectators talking through Scp1576. @@ -31,6 +32,22 @@ public class Scp1576Item : UsableItem /// public static IEnumerable ReceiverList => BaseScp1576Item.ValidatedReceivers.Select(x => Player.Get(x)); + /// + /// Gets the SCP-1576 item wrapper from the or creates a new one if it doesn't exist and the provided was not null. + /// + /// The of the item. + /// The requested item or null. + [return: NotNullIfNotNull(nameof(baseScp1576Item))] + public static Scp1576Item? Get(BaseScp1576Item? baseScp1576Item) + { + if (baseScp1576Item == null) + { + return null; + } + + return Dictionary.TryGetValue(baseScp1576Item, out Scp1576Item item) ? item : (Scp1576Item)CreateItemWrapper(baseScp1576Item); + } + /// /// An internal constructor to prevent external instantiation. /// @@ -41,16 +58,9 @@ internal Scp1576Item(BaseScp1576Item baseScp1576Item) Base = baseScp1576Item; if (CanCache) + { Dictionary.Add(baseScp1576Item, this); - } - - /// - /// An internal method to remove itself from the cache when the base object is destroyed. - /// - internal override void OnRemove() - { - base.OnRemove(); - Dictionary.Remove(Base); + } } /// @@ -59,16 +69,11 @@ internal override void OnRemove() public new BaseScp1576Item Base { get; } /// - /// Gets the SCP-1576 item wrapper from the or creates a new one if it doesn't exist and the provided was not null. + /// An internal method to remove itself from the cache when the base object is destroyed. /// - /// The of the item. - /// The requested item or null. - [return: NotNullIfNotNull(nameof(baseScp1576Item))] - public static Scp1576Item? Get(BaseScp1576Item? baseScp1576Item) + internal override void OnRemove() { - if (baseScp1576Item == null) - return null; - - return Dictionary.TryGetValue(baseScp1576Item, out Scp1576Item item) ? item : (Scp1576Item)CreateItemWrapper(baseScp1576Item); + base.OnRemove(); + Dictionary.Remove(Base); } } diff --git a/LabApi/Features/Wrappers/Items/Usable/Scp244Item.cs b/LabApi/Features/Wrappers/Items/Usable/Scp244Item.cs index 104326ad..7aa791dd 100644 --- a/LabApi/Features/Wrappers/Items/Usable/Scp244Item.cs +++ b/LabApi/Features/Wrappers/Items/Usable/Scp244Item.cs @@ -12,12 +12,28 @@ public class Scp244Item : UsableItem /// /// Contains all the cached SCP-244 items, accessible through their . /// - public new static Dictionary Dictionary { get; } = []; + public static new Dictionary Dictionary { get; } = []; /// /// A reference to all instances of . /// - public new static IReadOnlyCollection List => Dictionary.Values; + public static new IReadOnlyCollection List => Dictionary.Values; + + /// + /// Gets the SCP-244 item wrapper from the or creates a new one if it doesn't exist and the provided was not null. + /// + /// The of the item. + /// The requested item or null. + [return: NotNullIfNotNull(nameof(baseScp244Item))] + public static Scp244Item? Get(BaseScp244Item? baseScp244Item) + { + if (baseScp244Item == null) + { + return null; + } + + return Dictionary.TryGetValue(baseScp244Item, out Scp244Item item) ? item : (Scp244Item)CreateItemWrapper(baseScp244Item); + } /// /// An internal constructor to prevent external instantiation. @@ -29,16 +45,9 @@ internal Scp244Item(BaseScp244Item baseScp244Item) Base = baseScp244Item; if (CanCache) + { Dictionary.Add(baseScp244Item, this); - } - - /// - /// An internal method to remove itself from the cache when the base object is destroyed. - /// - internal override void OnRemove() - { - base.OnRemove(); - Dictionary.Remove(Base); + } } /// @@ -47,16 +56,11 @@ internal override void OnRemove() public new BaseScp244Item Base { get; } /// - /// Gets the SCP-244 item wrapper from the or creates a new one if it doesn't exist and the provided was not null. + /// An internal method to remove itself from the cache when the base object is destroyed. /// - /// The of the item. - /// The requested item or null. - [return: NotNullIfNotNull(nameof(baseScp244Item))] - public static Scp244Item? Get(BaseScp244Item? baseScp244Item) + internal override void OnRemove() { - if (baseScp244Item == null) - return null; - - return Dictionary.TryGetValue(baseScp244Item, out Scp244Item item) ? item : (Scp244Item)CreateItemWrapper(baseScp244Item); + base.OnRemove(); + Dictionary.Remove(Base); } } diff --git a/LabApi/Features/Wrappers/Items/Usable/Scp268Item.cs b/LabApi/Features/Wrappers/Items/Usable/Scp268Item.cs index c75ed92b..283d78df 100644 --- a/LabApi/Features/Wrappers/Items/Usable/Scp268Item.cs +++ b/LabApi/Features/Wrappers/Items/Usable/Scp268Item.cs @@ -12,12 +12,28 @@ public class Scp268Item : UsableItem /// /// Contains all the cached SCP-268 items, accessible through their . /// - public new static Dictionary Dictionary { get; } = []; + public static new Dictionary Dictionary { get; } = []; /// /// A reference to all instances of . /// - public new static IReadOnlyCollection List => Dictionary.Values; + public static new IReadOnlyCollection List => Dictionary.Values; + + /// + /// Gets the SCP-268 item wrapper from the or creates a new one if it doesn't exist and the provided was not null. + /// + /// The of the item. + /// The requested item or null. + [return: NotNullIfNotNull(nameof(scp268))] + public static Scp268Item? Get(Scp268? scp268) + { + if (scp268 == null) + { + return null; + } + + return Dictionary.TryGetValue(scp268, out Scp268Item item) ? item : (Scp268Item)CreateItemWrapper(scp268); + } /// /// An internal constructor to prevent external instantiation. @@ -29,16 +45,9 @@ internal Scp268Item(Scp268 scp268) Base = scp268; if (CanCache) + { Dictionary.Add(scp268, this); - } - - /// - /// An internal method to remove itself from the cache when the base object is destroyed. - /// - internal override void OnRemove() - { - base.OnRemove(); - Dictionary.Remove(Base); + } } /// @@ -59,16 +68,11 @@ public bool IsWorn } /// - /// Gets the SCP-268 item wrapper from the or creates a new one if it doesn't exist and the provided was not null. + /// An internal method to remove itself from the cache when the base object is destroyed. /// - /// The of the item. - /// The requested item or null. - [return: NotNullIfNotNull(nameof(scp268))] - public static Scp268Item? Get(Scp268? scp268) + internal override void OnRemove() { - if (scp268 == null) - return null; - - return Dictionary.TryGetValue(scp268, out Scp268Item item) ? item : (Scp268Item)CreateItemWrapper(scp268); + base.OnRemove(); + Dictionary.Remove(Base); } } diff --git a/LabApi/Features/Wrappers/Items/Usable/Scp330Item.cs b/LabApi/Features/Wrappers/Items/Usable/Scp330Item.cs index 072f7338..710f76a6 100644 --- a/LabApi/Features/Wrappers/Items/Usable/Scp330Item.cs +++ b/LabApi/Features/Wrappers/Items/Usable/Scp330Item.cs @@ -12,20 +12,36 @@ namespace LabApi.Features.Wrappers; /// public class Scp330Item : UsableItem { + /// + /// Maximum number of candies that can be contained in a bag. + /// + public const int MaxCandies = BaseScp330Item.MaxCandies; + /// /// Contains all the cached SCP-330 items, accessible through their . /// - public new static Dictionary Dictionary { get; } = []; + public static new Dictionary Dictionary { get; } = []; /// /// A reference to all instances of . /// - public new static IReadOnlyCollection List => Dictionary.Values; + public static new IReadOnlyCollection List => Dictionary.Values; /// - /// Maximum number of candies that can be contained in a bag. + /// Gets the SCP-330 item wrapper from the or creates a new one if it doesn't exist and the provided was not null. /// - public const int MaxCandies = BaseScp330Item.MaxCandies; + /// The of the item. + /// The requested item or null. + [return: NotNullIfNotNull(nameof(baseScp330Item))] + public static Scp330Item? Get(BaseScp330Item? baseScp330Item) + { + if (baseScp330Item == null) + { + return null; + } + + return Dictionary.TryGetValue(baseScp330Item, out Scp330Item item) ? item : (Scp330Item)CreateItemWrapper(baseScp330Item); + } /// /// An internal constructor to prevent external instantiation. @@ -37,16 +53,9 @@ internal Scp330Item(BaseScp330Item baseScp330Item) Base = baseScp330Item; if (CanCache) + { Dictionary.Add(baseScp330Item, this); - } - - /// - /// An internal method to remove itself from the cache when the base object is destroyed. - /// - internal override void OnRemove() - { - base.OnRemove(); - Dictionary.Remove(Base); + } } /// @@ -76,10 +85,14 @@ public void AddCandies(IEnumerable candies, bool sync = true) { IEnumerator enumerator = candies.GetEnumerator(); while (enumerator.MoveNext() && Base.Candies.Count < MaxCandies) + { Base.Candies.Add(enumerator.Current); + } if (sync) + { SyncCandies(); + } } /// @@ -94,10 +107,14 @@ public void RemoveCandies(IEnumerable candies, bool sync = true) { IEnumerator enumerator = candies.GetEnumerator(); while (enumerator.MoveNext() && !Base.Candies.IsEmpty()) + { Base.Candies.Remove(enumerator.Current); + } if (sync) + { SyncCandies(); + } } /// @@ -126,15 +143,21 @@ public void SetCandies(IEnumerable candies, bool sync = true) public bool TryDrop(CandyKindID kind, [NotNullWhen(true)] out Pickup? dropped) { dropped = null; - if(!Candies.Contains(kind)) + if (!Candies.Contains(kind)) + { return false; + } if (CurrentOwner == null) + { return false; + } dropped = Pickup.Create(Type, CurrentOwner.Position); if (dropped == null) + { return false; + } Scp330Pickup scp330 = (Scp330Pickup)dropped; scp330.ExposedCandy = kind; @@ -144,16 +167,11 @@ public bool TryDrop(CandyKindID kind, [NotNullWhen(true)] out Pickup? dropped) } /// - /// Gets the SCP-330 item wrapper from the or creates a new one if it doesn't exist and the provided was not null. + /// An internal method to remove itself from the cache when the base object is destroyed. /// - /// The of the item. - /// The requested item or null. - [return: NotNullIfNotNull(nameof(baseScp330Item))] - public static Scp330Item? Get(BaseScp330Item? baseScp330Item) + internal override void OnRemove() { - if (baseScp330Item == null) - return null; - - return Dictionary.TryGetValue(baseScp330Item, out Scp330Item item) ? item : (Scp330Item)CreateItemWrapper(baseScp330Item); + base.OnRemove(); + Dictionary.Remove(Base); } } diff --git a/LabApi/Features/Wrappers/Items/Usable/UsableItem.cs b/LabApi/Features/Wrappers/Items/Usable/UsableItem.cs index 02da0172..6d45cfad 100644 --- a/LabApi/Features/Wrappers/Items/Usable/UsableItem.cs +++ b/LabApi/Features/Wrappers/Items/Usable/UsableItem.cs @@ -14,33 +14,42 @@ public class UsableItem : Item /// /// Contains all the cached usable items, accessible through their . /// - public new static Dictionary Dictionary { get; } = []; + public static new Dictionary Dictionary { get; } = []; /// /// A reference to all instances of . /// - public new static IReadOnlyCollection List => Dictionary.Values; + public static new IReadOnlyCollection List => Dictionary.Values; + + /// + /// Gets the usable item wrapper from the or creates a new one if it doesn't exist and the provided was not null. + /// + /// The of the item. + /// The requested item or null. + [return: NotNullIfNotNull(nameof(baseUsableItem))] + public static UsableItem? Get(BaseUsableItem? baseUsableItem) + { + if (baseUsableItem == null) + { + return null; + } + + return Dictionary.TryGetValue(baseUsableItem, out UsableItem item) ? item : (UsableItem)CreateItemWrapper(baseUsableItem); + } /// /// An internal constructor to prevent external instantiation. /// /// The base object. internal UsableItem(BaseUsableItem baseUsableItem) - :base(baseUsableItem) + : base(baseUsableItem) { Base = baseUsableItem; if (CanCache) + { Dictionary.Add(baseUsableItem, this); - } - - /// - /// An internal method to remove itself from the cache when the base object is destroyed. - /// - internal override void OnRemove() - { - base.OnRemove(); - Dictionary.Remove(Base); + } } /// @@ -54,7 +63,9 @@ internal override void OnRemove() public bool IsUsing { get => Base.IsUsing; - set => Base.IsUsing = value; + set => UsableItemsController.ServerEmulateMessage( + Serial, + value ? StatusMessage.StatusType.Start : StatusMessage.StatusType.Cancel); } /// @@ -95,14 +106,19 @@ public float PersonalCooldownDuration get { if (CurrentOwner?.ReferenceHub == null || !UsableItemsController.GetHandler(CurrentOwner.ReferenceHub).PersonalCooldowns.TryGetValue(Type, out float time)) + { return 0; + } return time - Time.timeSinceLevelLoad; } + set { if (CurrentOwner?.ReferenceHub != null) + { UsableItemsController.GetHandler(CurrentOwner.ReferenceHub).PersonalCooldowns[Type] = Time.timeSinceLevelLoad + value; + } } } @@ -127,19 +143,14 @@ public float PersonalCooldownDuration /// /// The sounds range in meters. /// Returns true if item is being used, otherwise false. - public bool TryGetSoundEmissionRange(out float range) => Base.ServerTryGetSoundEmissionRange(out range); + public bool TryGetSoundEmissionRange(out float range) => Base.TryGetSoundEmissionRange(out range); /// - /// Gets the usable item wrapper from the or creates a new one if it doesn't exist and the provided was not null. + /// An internal method to remove itself from the cache when the base object is destroyed. /// - /// The of the item. - /// The requested item or null. - [return: NotNullIfNotNull(nameof(baseUsableItem))] - public static UsableItem? Get(BaseUsableItem? baseUsableItem) + internal override void OnRemove() { - if (baseUsableItem == null) - return null; - - return Dictionary.TryGetValue(baseUsableItem, out UsableItem item) ? item : (UsableItem)CreateItemWrapper(baseUsableItem); + base.OnRemove(); + Dictionary.Remove(Base); } } diff --git a/LabApi/Features/Wrappers/Pickups/AmmoPickup.cs b/LabApi/Features/Wrappers/Pickups/AmmoPickup.cs index 6be7fefd..681332cb 100644 --- a/LabApi/Features/Wrappers/Pickups/AmmoPickup.cs +++ b/LabApi/Features/Wrappers/Pickups/AmmoPickup.cs @@ -12,12 +12,28 @@ public class AmmoPickup : Pickup /// /// Contains all the cached ammo pickups, accessible through their . /// - public new static Dictionary Dictionary { get; } = []; + public static new Dictionary Dictionary { get; } = []; /// /// A reference to all instances of . /// - public new static IReadOnlyCollection List => Dictionary.Values; + public static new IReadOnlyCollection List => Dictionary.Values; + + /// + /// Gets the ammo pickup from the or creates a new if it doesn't exist and the provided was not . + /// + /// The if the pickup. + /// The requested pickup or . + [return: NotNullIfNotNull(nameof(pickup))] + public static AmmoPickup? Get(BaseAmmoPickup? pickup) + { + if (pickup == null) + { + return null; + } + + return Dictionary.TryGetValue(pickup, out AmmoPickup wrapper) ? wrapper : (AmmoPickup)CreateItemWrapper(pickup); + } /// /// An internal constructor to prevent external instantiation. @@ -29,16 +45,9 @@ internal AmmoPickup(BaseAmmoPickup baseAmmoPickup) Base = baseAmmoPickup; if (CanCache) + { Dictionary.Add(baseAmmoPickup, this); - } - - /// - /// A internal method to remove itself from the cache when the base object is destroyed. - /// - internal override void OnRemove() - { - base.OnRemove(); - Dictionary.Remove(Base); + } } /// @@ -56,16 +65,11 @@ public ushort Ammo } /// - /// Gets the ammo pickup from the or creates a new if it doesn't exist and the provided was not . + /// A internal method to remove itself from the cache when the base object is destroyed. /// - /// The if the pickup. - /// The requested pickup or . - [return: NotNullIfNotNull(nameof(pickup))] - public static AmmoPickup? Get(BaseAmmoPickup? pickup) + internal override void OnRemove() { - if (pickup == null) - return null; - - return Dictionary.TryGetValue(pickup, out AmmoPickup wrapper) ? wrapper : (AmmoPickup)CreateItemWrapper(pickup); + base.OnRemove(); + Dictionary.Remove(Base); } } diff --git a/LabApi/Features/Wrappers/Pickups/BodyArmorPickup.cs b/LabApi/Features/Wrappers/Pickups/BodyArmorPickup.cs index 643a268b..bc23c687 100644 --- a/LabApi/Features/Wrappers/Pickups/BodyArmorPickup.cs +++ b/LabApi/Features/Wrappers/Pickups/BodyArmorPickup.cs @@ -12,12 +12,28 @@ public class BodyArmorPickup : Pickup /// /// Contains all the cached body armor pickups, accessible through their . /// - public new static Dictionary Dictionary { get; } = []; + public static new Dictionary Dictionary { get; } = []; /// /// A reference to all instances of . /// - public new static IReadOnlyCollection List => Dictionary.Values; + public static new IReadOnlyCollection List => Dictionary.Values; + + /// + /// Gets the body armor pickup from the or creates a new if it doesn't exist and the provided was not . + /// + /// The if the pickup. + /// The requested pickup or . + [return: NotNullIfNotNull(nameof(pickup))] + public static BodyArmorPickup? Get(BaseBodyArmorPickup? pickup) + { + if (pickup == null) + { + return null; + } + + return Dictionary.TryGetValue(pickup, out BodyArmorPickup wrapper) ? wrapper : (BodyArmorPickup)CreateItemWrapper(pickup); + } /// /// An internal constructor to prevent external instantiation. @@ -29,16 +45,9 @@ internal BodyArmorPickup(BaseBodyArmorPickup baseBodyArmorPickup) Base = baseBodyArmorPickup; if (CanCache) + { Dictionary.Add(baseBodyArmorPickup, this); - } - - /// - /// A internal method to remove itself from the cache when the base object is destroyed. - /// - internal override void OnRemove() - { - base.OnRemove(); - Dictionary.Remove(Base); + } } /// @@ -47,16 +56,11 @@ internal override void OnRemove() public new BaseBodyArmorPickup Base { get; } /// - /// Gets the body armor pickup from the or creates a new if it doesn't exist and the provided was not . + /// A internal method to remove itself from the cache when the base object is destroyed. /// - /// The if the pickup. - /// The requested pickup or . - [return: NotNullIfNotNull(nameof(pickup))] - public static BodyArmorPickup? Get(BaseBodyArmorPickup? pickup) + internal override void OnRemove() { - if (pickup == null) - return null; - - return Dictionary.TryGetValue(pickup, out BodyArmorPickup wrapper) ? wrapper : (BodyArmorPickup)CreateItemWrapper(pickup); + base.OnRemove(); + Dictionary.Remove(Base); } } diff --git a/LabApi/Features/Wrappers/Pickups/FirearmPickup.cs b/LabApi/Features/Wrappers/Pickups/FirearmPickup.cs index 401abff3..d197c9ba 100644 --- a/LabApi/Features/Wrappers/Pickups/FirearmPickup.cs +++ b/LabApi/Features/Wrappers/Pickups/FirearmPickup.cs @@ -14,12 +14,28 @@ public class FirearmPickup : Pickup /// /// Contains all the cached firearm pickups, accessible through their . /// - public new static Dictionary Dictionary { get; } = []; + public static new Dictionary Dictionary { get; } = []; /// /// A reference to all instances of . /// - public new static IReadOnlyCollection List => Dictionary.Values; + public static new IReadOnlyCollection List => Dictionary.Values; + + /// + /// Gets the firearm pickup from the or creates a new if it doesn't exist and the provided was not . + /// + /// The if the pickup. + /// The requested pickup or . + [return: NotNullIfNotNull(nameof(pickup))] + public static FirearmPickup? Get(BaseFirearmPickup? pickup) + { + if (pickup == null) + { + return null; + } + + return Dictionary.TryGetValue(pickup, out FirearmPickup wrapper) ? wrapper : (FirearmPickup)CreateItemWrapper(pickup); + } /// /// An internal constructor to prevent external instantiation. @@ -31,16 +47,9 @@ internal FirearmPickup(BaseFirearmPickup baseFirearmPickup) Base = baseFirearmPickup; if (CanCache) + { Dictionary.Add(baseFirearmPickup, this); - } - - /// - /// A internal method to remove itself from the cache when the base object is destroyed. - /// - internal override void OnRemove() - { - base.OnRemove(); - Dictionary.Remove(Base); + } } /// @@ -63,16 +72,11 @@ public uint AttachmentCode } /// - /// Gets the firearm pickup from the or creates a new if it doesn't exist and the provided was not . + /// A internal method to remove itself from the cache when the base object is destroyed. /// - /// The if the pickup. - /// The requested pickup or . - [return: NotNullIfNotNull(nameof(pickup))] - public static FirearmPickup? Get(BaseFirearmPickup? pickup) + internal override void OnRemove() { - if (pickup == null) - return null; - - return Dictionary.TryGetValue(pickup, out FirearmPickup wrapper) ? wrapper : (FirearmPickup)CreateItemWrapper(pickup); + base.OnRemove(); + Dictionary.Remove(Base); } } diff --git a/LabApi/Features/Wrappers/Pickups/JailbirdPickup.cs b/LabApi/Features/Wrappers/Pickups/JailbirdPickup.cs index f0ea39cf..6561da44 100644 --- a/LabApi/Features/Wrappers/Pickups/JailbirdPickup.cs +++ b/LabApi/Features/Wrappers/Pickups/JailbirdPickup.cs @@ -13,12 +13,28 @@ public class JailbirdPickup : Pickup /// /// Contains all the cached ammo pickups, accessible through their . /// - public new static Dictionary Dictionary { get; } = []; + public static new Dictionary Dictionary { get; } = []; /// /// A reference to all instances of . /// - public new static IReadOnlyCollection List => Dictionary.Values; + public static new IReadOnlyCollection List => Dictionary.Values; + + /// + /// Gets the jailbird pickup from the or creates a new if it doesn't exist and the provided was not . + /// + /// The if the pickup. + /// The requested pickup or . + [return: NotNullIfNotNull(nameof(pickup))] + public static JailbirdPickup? Get(BaseJailbirdPickup? pickup) + { + if (pickup == null) + { + return null; + } + + return Dictionary.TryGetValue(pickup, out JailbirdPickup wrapper) ? wrapper : (JailbirdPickup)CreateItemWrapper(pickup); + } /// /// An internal constructor to prevent external instantiation. @@ -30,16 +46,9 @@ internal JailbirdPickup(BaseJailbirdPickup baseJailbirdPickup) Base = baseJailbirdPickup; if (CanCache) + { Dictionary.Add(baseJailbirdPickup, this); - } - - /// - /// A internal method to remove itself from the cache when the base object is destroyed. - /// - internal override void OnRemove() - { - base.OnRemove(); - Dictionary.Remove(Base); + } } /// @@ -75,16 +84,11 @@ public JailbirdWearState WearState } /// - /// Gets the jailbird pickup from the or creates a new if it doesn't exist and the provided was not . + /// A internal method to remove itself from the cache when the base object is destroyed. /// - /// The if the pickup. - /// The requested pickup or . - [return: NotNullIfNotNull(nameof(pickup))] - public static JailbirdPickup? Get(BaseJailbirdPickup? pickup) + internal override void OnRemove() { - if (pickup == null) - return null; - - return Dictionary.TryGetValue(pickup, out JailbirdPickup wrapper) ? wrapper : (JailbirdPickup)CreateItemWrapper(pickup); + base.OnRemove(); + Dictionary.Remove(Base); } } diff --git a/LabApi/Features/Wrappers/Pickups/KeycardPickup.cs b/LabApi/Features/Wrappers/Pickups/KeycardPickup.cs index f0741a9e..71a58ea6 100644 --- a/LabApi/Features/Wrappers/Pickups/KeycardPickup.cs +++ b/LabApi/Features/Wrappers/Pickups/KeycardPickup.cs @@ -12,12 +12,28 @@ public class KeycardPickup : Pickup /// /// Contains all the cached keycard pickups, accessible through their . /// - public new static Dictionary Dictionary { get; } = []; + public static new Dictionary Dictionary { get; } = []; /// /// A reference to all instances of . /// - public new static IReadOnlyCollection List => Dictionary.Values; + public static new IReadOnlyCollection List => Dictionary.Values; + + /// + /// Gets the keycard pickup from the or creates a new if it doesn't exist and the provided was not . + /// + /// The if the pickup. + /// The requested pickup or . + [return: NotNullIfNotNull(nameof(pickup))] + public static KeycardPickup? Get(BaseKeycardPickup? pickup) + { + if (pickup == null) + { + return null; + } + + return Dictionary.TryGetValue(pickup, out KeycardPickup wrapper) ? wrapper : (KeycardPickup)CreateItemWrapper(pickup); + } /// /// An internal constructor to prevent external instantiation. @@ -29,16 +45,9 @@ internal KeycardPickup(BaseKeycardPickup baseKeycardPickup) Base = baseKeycardPickup; if (CanCache) + { Dictionary.Add(baseKeycardPickup, this); - } - - /// - /// A internal method to remove itself from the cache when the base object is destroyed. - /// - internal override void OnRemove() - { - base.OnRemove(); - Dictionary.Remove(Base); + } } /// @@ -47,16 +56,11 @@ internal override void OnRemove() public new BaseKeycardPickup Base { get; } /// - /// Gets the keycard pickup from the or creates a new if it doesn't exist and the provided was not . + /// A internal method to remove itself from the cache when the base object is destroyed. /// - /// The if the pickup. - /// The requested pickup or . - [return: NotNullIfNotNull(nameof(pickup))] - public static KeycardPickup? Get(BaseKeycardPickup? pickup) + internal override void OnRemove() { - if (pickup == null) - return null; - - return Dictionary.TryGetValue(pickup, out KeycardPickup wrapper) ? wrapper : (KeycardPickup)CreateItemWrapper(pickup); + base.OnRemove(); + Dictionary.Remove(Base); } } diff --git a/LabApi/Features/Wrappers/Pickups/MicroHIDPickup.cs b/LabApi/Features/Wrappers/Pickups/MicroHIDPickup.cs index 6d30c11d..0262d429 100644 --- a/LabApi/Features/Wrappers/Pickups/MicroHIDPickup.cs +++ b/LabApi/Features/Wrappers/Pickups/MicroHIDPickup.cs @@ -1,4 +1,6 @@ -using InventorySystem.Items.MicroHID.Modules; +using InventorySystem; +using InventorySystem.Items.MicroHID.Modules; +using LabApi.Features.Console; using System.Collections.Generic; using System.Diagnostics.CodeAnalysis; using BaseMicroHIDPickup = InventorySystem.Items.MicroHID.MicroHIDPickup; @@ -13,12 +15,28 @@ public class MicroHIDPickup : Pickup /// /// Contains all the cached micro hid pickups, accessible through their . /// - public new static Dictionary Dictionary { get; } = []; + public static new Dictionary Dictionary { get; } = []; /// /// A reference to all instances of . /// - public new static IReadOnlyCollection List => Dictionary.Values; + public static new IReadOnlyCollection List => Dictionary.Values; + + /// + /// Gets the micro hid pickup from the or creates a new if it doesn't exist and the provided was not . + /// + /// The if the pickup. + /// The requested pickup or . + [return: NotNullIfNotNull(nameof(pickup))] + public static MicroHIDPickup? Get(BaseMicroHIDPickup? pickup) + { + if (pickup == null) + { + return null; + } + + return Dictionary.TryGetValue(pickup, out MicroHIDPickup wrapper) ? wrapper : (MicroHIDPickup)CreateItemWrapper(pickup); + } /// /// An internal constructor to prevent external instantiation. @@ -31,16 +49,9 @@ internal MicroHIDPickup(BaseMicroHIDPickup baseMicroHIDPickup) BaseCycleController = CycleSyncModule.GetCycleController(Serial); if (CanCache) + { Dictionary.Add(baseMicroHIDPickup, this); - } - - /// - /// A internal method to remove itself from the cache when the base object is destroyed. - /// - internal override void OnRemove() - { - base.OnRemove(); - Dictionary.Remove(Base); + } } /// @@ -71,6 +82,28 @@ public MicroHidFiringMode FiringMode set => BaseCycleController.LastFiringMode = value; } + /// + /// Gets or sets the energy amount in this Micro-HID pickup. + /// The energy value, automatically clamped, ranges from 0f to 1f. + /// + public float Energy + { + get + { + return EnergyManagerModule.GetEnergy(Serial); + } + set + { + if (!InventoryItemLoader.TryGetItem(ItemType.MicroHID, out InventorySystem.Items.MicroHID.MicroHIDItem item)) + { + Logger.Error("Unable to get the base microhid item!"); + return; + } + + item.EnergyManager.ServerSetEnergy(Serial, value); + } + } + /// /// The progress from 0 to 1 for how ready the micro is to fire. /// Goes up when winding up, and down when winding down. @@ -83,16 +116,11 @@ public MicroHidFiringMode FiringMode public float PhaseElapsed => BaseCycleController.CurrentPhaseElapsed; /// - /// Gets the micro hid pickup from the or creates a new if it doesn't exist and the provided was not . + /// A internal method to remove itself from the cache when the base object is destroyed. /// - /// The if the pickup. - /// The requested pickup or . - [return: NotNullIfNotNull(nameof(pickup))] - public static MicroHIDPickup? Get(BaseMicroHIDPickup? pickup) + internal override void OnRemove() { - if (pickup == null) - return null; - - return Dictionary.TryGetValue(pickup, out MicroHIDPickup wrapper) ? wrapper : (MicroHIDPickup)CreateItemWrapper(pickup); + base.OnRemove(); + Dictionary.Remove(Base); } } diff --git a/LabApi/Features/Wrappers/Pickups/Pickup.cs b/LabApi/Features/Wrappers/Pickups/Pickup.cs index 855044a1..2d178b79 100644 --- a/LabApi/Features/Wrappers/Pickups/Pickup.cs +++ b/LabApi/Features/Wrappers/Pickups/Pickup.cs @@ -3,11 +3,10 @@ using InventorySystem.Items; using InventorySystem.Items.Pickups; using InventorySystem.Items.ThrowableProjectiles; +using LabApi.Events.Arguments.ServerEvents; +using LabApi.Events.Handlers; using Mirror; using System; -using InventorySystem.Items.ThrowableProjectiles; -using LabApi.Events.Handlers; -using LabApi.Events.Arguments.ServerEvents; using System.Collections.Generic; using System.Diagnostics.CodeAnalysis; using UnityEngine; @@ -21,6 +20,106 @@ namespace LabApi.Features.Wrappers; /// public class Pickup { + /// + /// Contains all the handlers for constructing wrappers for the associated base game types. + /// + private static readonly Dictionary> TypeWrappers = []; + + /// + /// Contains all the cached items that have a none zero serial, accessible through their serial. + /// + /// + /// Item pickups spawned by the map do not have a serial until they are unlocked so may not be cached here. + /// Use or instead if you need all item pickups. + /// + public static Dictionary SerialCache { get; } = []; + + /// + /// Contains all the cached item pickups, accessible through their . + /// + public static Dictionary Dictionary { get; } = []; + + /// + /// A reference to all instances of . + /// + public static IReadOnlyCollection List => Dictionary.Values; + + /// + /// Gets the pickup wrapper from the or creates a new one if it doesn't exist. + /// + /// The of the pickup. + /// The requested item . + [return: NotNullIfNotNull(nameof(itemPickupBase))] + public static Pickup? Get(ItemPickupBase? itemPickupBase) + { + if (itemPickupBase == null) + { + return null; + } + + if (Dictionary.TryGetValue(itemPickupBase, out Pickup pickup)) + { + return pickup; + } + + return CreateItemWrapper(itemPickupBase); + } + + /// + /// Gets the pickup wrapper from the . + /// + /// The serial of the pickup. + /// The requested item or null if it doesn't exist. + public static Pickup? Get(ushort itemSerial) => SerialCache.GetValueOrDefault(itemSerial); + + /// + /// Tries to get the pickup wrapper from the . + /// + /// The serial of the pickup. + /// The requested item or null if it doesn't exist. + /// True of the pickup exists, otherwise false. + public static bool TryGet(ushort itemSerial, [NotNullWhen(true)] out Pickup? pickup) => SerialCache.TryGetValue(itemSerial, out pickup); + + /// + /// Creates a new . + /// + /// The . + /// The initial position. + /// The instantiated . + /// The pickup is only spawned on the server, to spawn the pickup for clients use . + public static Pickup? Create(ItemType type, Vector3 position) => Create(type, position, Quaternion.identity, Vector3.one); + + /// + /// Creates a new . + /// + /// The . + /// The initial position. + /// The initial rotation. + /// The instantiated . + /// The pickup is only spawned on the server, to spawn the pickup for clients use . + public static Pickup? Create(ItemType type, Vector3 position, Quaternion rotation) => Create(type, position, rotation, Vector3.one); + + /// + /// Creates a new . + /// + /// The . + /// The initial position. + /// The initial rotation. + /// The initial scale. + /// The instantiated . + /// The pickup is only spawned on the server, to spawn the pickup for clients use . + public static Pickup? Create(ItemType type, Vector3 position, Quaternion rotation, Vector3 scale) + { + if (type == ItemType.None || !InventoryItemLoader.AvailableItems.TryGetValue(type, out ItemBase itemBase)) + { + return null; + } + + ItemPickupBase newPickupBase = InventoryExtensions.ServerCreatePickup(itemBase, new PickupSyncInfo(type, itemBase.Weight), position, rotation, false); + newPickupBase.transform.localScale = scale; + return Get(newPickupBase); + } + /// /// Initializes the class. /// @@ -34,6 +133,10 @@ internal static void Initialize() Register(n => new ExplosiveGrenadeProjectile(n)); Register((InventorySystem.Items.ThrowableProjectiles.Scp018Projectile n) => new Scp018Projectile(n)); Register((InventorySystem.Items.ThrowableProjectiles.Scp2176Projectile n) => new Scp2176Projectile(n)); + Register((InventorySystem.Items.ThrowableProjectiles.SingleTrajectoryProjectile n) => new SingleTrajectoryProjectile(n)); + Register((InventorySystem.Items.ThrowableProjectiles.FlybyDetectorProjectile n) => new FlybyDetectorProjectile(n)); + Register((InventorySystem.Items.ThrowableProjectiles.Scp2536Projectile n) => new Scp2536Projectile(n)); + Register((InventorySystem.Items.ThrowableProjectiles.SnowballProjectile n) => new SnowballProjectile(n)); Register(x => new AmmoPickup(x)); Register(x => new BodyArmorPickup(x)); @@ -50,28 +153,100 @@ internal static void Initialize() } /// - /// Contains all the handlers for constructing wrappers for the associated base game types. + /// Creates a new wrapper from the base pickup object. /// - private static readonly Dictionary> typeWrappers = []; + /// The base object. + /// The newly created wrapper. + protected static Pickup CreateItemWrapper(ItemPickupBase pickupBase) + { + if (TypeWrappers.TryGetValue(pickupBase.GetType(), out Func ctorFunc)) + { + return ctorFunc(pickupBase); + } + + Console.Logger.Warn($"Failed to find pickup wrapper for type {pickupBase.GetType()}"); + return new Pickup(pickupBase); + } /// - /// Contains all the cached items that have a none zero serial, accessible through their serial. + /// A private method to handle the creation of new pickups in the server. /// - /// - /// Item pickups spawned by the map do not have a serial until they are unlocked so may not be cached here. - /// Use or instead if you need all item pickups. - /// - public static Dictionary SerialCache { get; } = []; + /// The created instance. + private static void AddPickup(ItemPickupBase pickup) + { + try + { + if (!Dictionary.ContainsKey(pickup)) + { + Pickup wrapper = CreateItemWrapper(pickup); + ServerEvents.OnPickupCreated(new PickupCreatedEventArgs(wrapper)); + } + } + catch (Exception e) + { + Console.Logger.Error($"Failed to handle pickup creation with error: {e}"); + } + } /// - /// Contains all the cached item pickups, accessible through their . + /// A private method to handle the removal of pickups from the server. /// - public static Dictionary Dictionary { get; } = []; + /// The to be destroyed instance. + private static void RemovePickup(ItemPickupBase pickup) + { + try + { + if (Dictionary.TryGetValue(pickup, out Pickup item)) + { + item.OnRemove(); + } + + ServerEvents.OnPickupDestroyed(new PickupDestroyedEventArgs(item)); + } + catch (Exception e) + { + Console.Logger.Error($"Failed to handle pickup destruction with error: {e}"); + } + } /// - /// A reference to all instances of . + /// A private method to handle the addition of wrapper handlers. /// - public static IReadOnlyCollection List => Dictionary.Values; + /// The derived base game type to handle. + /// A handler to construct the wrapper with the base game instance. + private static void Register(Func constructor) + where T : ItemPickupBase + { + TypeWrappers.Add(typeof(T), x => constructor((T)x)); + } + + /// + /// A protected constructor to prevent external instantiation. + /// + /// The of the pickup. + protected Pickup(ItemPickupBase itemPickupBase) + { + Base = itemPickupBase; + GameObject = itemPickupBase.gameObject; + Transform = itemPickupBase.transform; + IsPrefab = InventoryItemLoader.TryGetItem(itemPickupBase.ItemId.TypeId, out ItemBase prefab) && prefab.PickupDropModel == itemPickupBase; + + if (CanCache) + { + if (Dictionary.ContainsKey(itemPickupBase)) + { + Console.Logger.InternalError($"Failed to create a pickup for base: {itemPickupBase}"); + return; + } + + Dictionary.Add(itemPickupBase, this); + + if (itemPickupBase.Info.Serial != 0) + { + SerialCache[itemPickupBase.Info.Serial] = this; + } + } + } /// /// The of the pickup. @@ -83,6 +258,9 @@ internal static void Initialize() /// public NetworkIdentity NetworkIdentity => Base.netIdentity; + /// + /// THe of the pickup. + /// /// /// Will be null if the is not a e.g. when SCP018 it is in its "Activated" state and uses an alternate physics module. /// Use instead for those cases. @@ -153,7 +331,7 @@ public float Weight get => Base.Info.WeightKg; set => Base.NetworkInfo = Base.Info with { - WeightKg = value + WeightKg = value, }; } @@ -165,7 +343,7 @@ public bool IsLocked get => Base.Info.Locked; set => Base.NetworkInfo = Base.Info with { - Locked = value + Locked = value, }; } @@ -177,7 +355,7 @@ public bool IsInUse get => Base.Info.InUse; set => Base.NetworkInfo = Base.Info with { - InUse = value + InUse = value, }; } @@ -217,36 +395,7 @@ public Quaternion Rotation /// /// Gets whether the item wrapper is allowed to be cached. /// - protected bool CanCache => !IsDestroyed && !IsPrefab; - - /// - /// A protected constructor to prevent external instantiation. - /// - /// The of the pickup. - protected Pickup(ItemPickupBase itemPickupBase) - { - Base = itemPickupBase; - GameObject = itemPickupBase.gameObject; - Transform = itemPickupBase.transform; - IsPrefab = InventoryItemLoader.TryGetItem(itemPickupBase.ItemId.TypeId, out ItemBase prefab) && prefab.PickupDropModel == itemPickupBase; - - if (CanCache) - { - Dictionary.Add(itemPickupBase, this); - - if (itemPickupBase.Info.Serial != 0) - SerialCache[itemPickupBase.Info.Serial] = this; - } - } - - /// - /// An internal virtual method to signal to derived implementations to uncache when the base object is destroyed. - /// - internal virtual void OnRemove() - { - Dictionary.Remove(Base); - SerialCache.Remove(Serial); - } + protected bool CanCache => !IsDestroyed && !IsPrefab && Base.isActiveAndEnabled; /// /// Spawns the pickup. @@ -271,135 +420,11 @@ public override string ToString() } /// - /// Gets the pickup wrapper from the or creates a new one if it doesn't exist. - /// - /// The of the pickup. - /// The requested item . - [return: NotNullIfNotNull(nameof(itemPickupBase))] - public static Pickup? Get(ItemPickupBase? itemPickupBase) - { - if (itemPickupBase == null) - return null; - - if (Dictionary.TryGetValue(itemPickupBase, out Pickup pickup)) - return pickup; - - return CreateItemWrapper(itemPickupBase); - } - - /// - /// Gets the pickup wrapper from the . - /// - /// The serial of the pickup. - /// The requested item or null if it doesn't exist. - public static Pickup? Get(ushort itemSerial) => SerialCache.GetValueOrDefault(itemSerial); - - /// - /// Tries to get the pickup wrapper from the . - /// - /// The serial of the pickup. - /// The requested item or null if it doesn't exist. - /// True of the pickup exists, otherwise false. - public static bool TryGet(ushort itemSerial, [NotNullWhen(true)] out Pickup? pickup) => SerialCache.TryGetValue(itemSerial, out pickup); - - /// - /// Creates a new . - /// - /// The . - /// The initial position. - /// The instantiated - /// The pickup is only spawned on the server, to spawn the pickup for clients use . - public static Pickup? Create(ItemType type, Vector3 position) => Create(type, position, Quaternion.identity, Vector3.one); - - /// - /// Creates a new . - /// - /// The . - /// The initial position. - /// The initial rotation. - /// The instantiated - /// The pickup is only spawned on the server, to spawn the pickup for clients use . - public static Pickup? Create(ItemType type, Vector3 position, Quaternion rotation) => Create(type, position, rotation, Vector3.one); - - /// - /// Creates a new . - /// - /// The . - /// The initial position. - /// The initial rotation. - /// The initial scale. - /// The instantiated - /// The pickup is only spawned on the server, to spawn the pickup for clients use . - public static Pickup? Create(ItemType type, Vector3 position, Quaternion rotation, Vector3 scale) - { - if (type == ItemType.None || !InventoryItemLoader.AvailableItems.TryGetValue(type, out ItemBase itemBase)) - return null; - - ItemPickupBase newPickupBase = InventoryExtensions.ServerCreatePickup(itemBase, new PickupSyncInfo(type, itemBase.Weight), position, rotation, false); - newPickupBase.transform.localScale = scale; - return Get(newPickupBase); - } - - /// - /// A private method to handle the creation of new pickups in the server. - /// - /// The created instance. - private static void AddPickup(ItemPickupBase pickup) - { - try - { - if (!Dictionary.ContainsKey(pickup)) - { - Pickup wrapper = CreateItemWrapper(pickup); - ServerEvents.OnPickupCreated(new PickupCreatedEventArgs(wrapper)); - } - } - catch(Exception e) - { - Console.Logger.Error($"Failed to handle pickup creation with error: {e}"); - } - } - - /// - /// A private method to handle the removal of pickups from the server. - /// - /// The to be destroyed instance. - private static void RemovePickup(ItemPickupBase pickup) - { - try - { - if (Dictionary.TryGetValue(pickup, out Pickup item)) - item.OnRemove(); - - ServerEvents.OnPickupDestroyed(new PickupDestroyedEventArgs(item)); - } - catch(Exception e) - { - Console.Logger.Error($"Failed to handle pickup destruction with error: {e}"); - } - } - - /// - /// A private method to handle the addition of wrapper handlers. - /// - /// The derived base game type to handle. - /// A handler to construct the wrapper with the base game instance. - private static void Register(Func constructor) where T : ItemPickupBase - { - typeWrappers.Add(typeof(T), x => constructor((T)x)); - } - - /// - /// Creates a new wrapper from the base pickup object. + /// An internal virtual method to signal to derived implementations to uncache when the base object is destroyed. /// - /// The base object. - /// The newly created wrapper. - protected static Pickup CreateItemWrapper(ItemPickupBase pickupBase) + internal virtual void OnRemove() { - if (typeWrappers.TryGetValue(pickupBase.GetType(), out Func ctorFunc)) - return ctorFunc(pickupBase); - - Console.Logger.Warn($"Failed to find pickup wrapper for type {pickupBase.GetType()}"); - return new Pickup(pickupBase); + Dictionary.Remove(Base); + SerialCache.Remove(Serial); } } diff --git a/LabApi/Features/Wrappers/Pickups/Projectiles/FlybyDetectorProjectile.cs b/LabApi/Features/Wrappers/Pickups/Projectiles/FlybyDetectorProjectile.cs new file mode 100644 index 00000000..3c012784 --- /dev/null +++ b/LabApi/Features/Wrappers/Pickups/Projectiles/FlybyDetectorProjectile.cs @@ -0,0 +1,65 @@ +using System.Collections.Generic; +using System.Diagnostics.CodeAnalysis; +using BaseFlybyDetectorProjectile = InventorySystem.Items.ThrowableProjectiles.FlybyDetectorProjectile; + +namespace LabApi.Features.Wrappers; + +/// +/// The wrapper representing pre-calculated player detector trajectory. +/// +public class FlybyDetectorProjectile : SingleTrajectoryProjectile +{ + /// + /// Contains all the cached projectiles, accessible through their . + /// + public static new Dictionary Dictionary { get; } = []; + + /// + /// A reference to all instances of . + /// + public static new IReadOnlyCollection List => Dictionary.Values; + + /// + /// Gets the projectile wrapper from the or creates a new if it doesn't exist and the provided was not . + /// + /// The if the projectile. + /// The requested wrapper or . + [return: NotNullIfNotNull(nameof(projectile))] + public static FlybyDetectorProjectile? Get(BaseFlybyDetectorProjectile? projectile) + { + if (projectile == null) + { + return null; + } + + return Dictionary.TryGetValue(projectile, out FlybyDetectorProjectile wrapper) ? wrapper : (FlybyDetectorProjectile)CreateItemWrapper(projectile); + } + + /// + /// A protected constructor to prevent external instantiation. + /// + /// The of the pickup. + internal FlybyDetectorProjectile(BaseFlybyDetectorProjectile projectilePickup) + : base(projectilePickup) + { + Base = projectilePickup; + + if (CanCache) + { + Dictionary.Add(projectilePickup, this); + } + } + + /// + /// The of the pickup. + /// + public new BaseFlybyDetectorProjectile Base { get; } + + /// + internal override void OnRemove() + { + base.OnRemove(); + + Dictionary.Remove(Base); + } +} diff --git a/LabApi/Features/Wrappers/Pickups/Projectiles/Grenades/ExplosiveGrenadeProjectile.cs b/LabApi/Features/Wrappers/Pickups/Projectiles/Grenades/ExplosiveGrenadeProjectile.cs index 57462b09..543f3fe4 100644 --- a/LabApi/Features/Wrappers/Pickups/Projectiles/Grenades/ExplosiveGrenadeProjectile.cs +++ b/LabApi/Features/Wrappers/Pickups/Projectiles/Grenades/ExplosiveGrenadeProjectile.cs @@ -20,16 +20,35 @@ public class ExplosiveGrenadeProjectile : TimedGrenadeProjectile /// public static new IReadOnlyCollection List => Dictionary.Values; + /// + /// Gets the explosion grenade from the or creates a new one if it doesn't exist and the provided was not . + /// + /// The of the projectile. + /// The requested projectile or . + [return: NotNullIfNotNull(nameof(projectile))] + public static ExplosiveGrenadeProjectile? Get(ExplosionGrenade? projectile) + { + if (projectile == null) + { + return null; + } + + return Dictionary.TryGetValue(projectile, out ExplosiveGrenadeProjectile wrapper) ? wrapper : (ExplosiveGrenadeProjectile)CreateItemWrapper(projectile); + } + /// /// A protected constructor to prevent external instantiation. /// /// The of the pickup. - internal ExplosiveGrenadeProjectile(ExplosionGrenade projectilePickup) : base(projectilePickup) + internal ExplosiveGrenadeProjectile(ExplosionGrenade projectilePickup) + : base(projectilePickup) { Base = projectilePickup; if (CanCache) + { Dictionary.Add(projectilePickup, this); + } } /// @@ -71,19 +90,4 @@ internal override void OnRemove() Dictionary.Remove(Base); } - - /// - /// Gets the explosion grenade from the or creates a new one if it doesn't exist and the provided was not . - /// - /// The of the projectile. - /// The requested projectile or . - [return: NotNullIfNotNull(nameof(projectile))] - public static ExplosiveGrenadeProjectile? Get(ExplosionGrenade? projectile) - { - if (projectile == null) - return null; - - return Dictionary.TryGetValue(projectile, out ExplosiveGrenadeProjectile wrapper) ? wrapper : (ExplosiveGrenadeProjectile)CreateItemWrapper(projectile); - } } - diff --git a/LabApi/Features/Wrappers/Pickups/Projectiles/Grenades/FlashbangProjectile.cs b/LabApi/Features/Wrappers/Pickups/Projectiles/Grenades/FlashbangProjectile.cs index fac43753..0ad15571 100644 --- a/LabApi/Features/Wrappers/Pickups/Projectiles/Grenades/FlashbangProjectile.cs +++ b/LabApi/Features/Wrappers/Pickups/Projectiles/Grenades/FlashbangProjectile.cs @@ -20,16 +20,35 @@ public class FlashbangProjectile : TimedGrenadeProjectile /// public static new IReadOnlyCollection List => Dictionary.Values; + /// + /// Gets the flashbang from the or creates a new one if it doesn't exist and the provided was not . + /// + /// The of the projectile. + /// The requested projectile or . + [return: NotNullIfNotNull(nameof(projectile))] + public static FlashbangProjectile? Get(FlashbangGrenade? projectile) + { + if (projectile == null) + { + return null; + } + + return Dictionary.TryGetValue(projectile, out FlashbangProjectile wrapper) ? wrapper : (FlashbangProjectile)CreateItemWrapper(projectile); + } + /// /// A protected constructor to prevent external instantiation. /// /// The of the pickup. - internal FlashbangProjectile(FlashbangGrenade projectilePickup) : base(projectilePickup) + internal FlashbangProjectile(FlashbangGrenade projectilePickup) + : base(projectilePickup) { Base = projectilePickup; if (CanCache) + { Dictionary.Add(projectilePickup, this); + } } /// @@ -48,7 +67,7 @@ public LayerMask BlockingMask /// /// Gets or sets the base blind time to affect people with. - /// Note that this value is affected by distance from the grenade aswell as whether the player is looking at it and if it is on surface. + /// Note that this value is affected by distance from the grenade as well as whether the player is looking at it and if it is on surface. /// public float BaseBlindTime { @@ -63,19 +82,4 @@ internal override void OnRemove() Dictionary.Remove(Base); } - - /// - /// Gets the flashbang from the or creates a new one if it doesn't exist and the provided was not . - /// - /// The of the projectile. - /// The requested projectile or . - [return: NotNullIfNotNull(nameof(projectile))] - public static FlashbangProjectile? Get(FlashbangGrenade? projectile) - { - if (projectile == null) - return null; - - return Dictionary.TryGetValue(projectile, out FlashbangProjectile wrapper) ? wrapper : (FlashbangProjectile)CreateItemWrapper(projectile); - } } - diff --git a/LabApi/Features/Wrappers/Pickups/Projectiles/Grenades/Scp018Projectile.cs b/LabApi/Features/Wrappers/Pickups/Projectiles/Grenades/Scp018Projectile.cs index d699577e..226ca4a1 100644 --- a/LabApi/Features/Wrappers/Pickups/Projectiles/Grenades/Scp018Projectile.cs +++ b/LabApi/Features/Wrappers/Pickups/Projectiles/Grenades/Scp018Projectile.cs @@ -1,5 +1,4 @@ using InventorySystem.Items.Pickups; -using InventorySystem.Items.ThrowableProjectiles; using System.Collections.Generic; using System.Diagnostics.CodeAnalysis; using UnityEngine; @@ -21,16 +20,35 @@ public class Scp018Projectile : TimedGrenadeProjectile /// public static new IReadOnlyCollection List => Dictionary.Values; + /// + /// Gets the Scp-018 from the or creates a new one if it doesn't exist and the provided was not . + /// + /// The of the projectile. + /// The requested projectile or . + [return: NotNullIfNotNull(nameof(projectile))] + public static Scp018Projectile? Get(InventorySystem.Items.ThrowableProjectiles.Scp018Projectile? projectile) + { + if (projectile == null) + { + return null; + } + + return Dictionary.TryGetValue(projectile, out Scp018Projectile wrapper) ? wrapper : (Scp018Projectile)CreateItemWrapper(projectile); + } + /// /// A protected constructor to prevent external instantiation. /// /// The of the pickup. - internal Scp018Projectile(InventorySystem.Items.ThrowableProjectiles.Scp018Projectile projectilePickup) : base(projectilePickup) + internal Scp018Projectile(InventorySystem.Items.ThrowableProjectiles.Scp018Projectile projectilePickup) + : base(projectilePickup) { Base = projectilePickup; if (CanCache) + { Dictionary.Add(projectilePickup, this); + } } /// @@ -49,12 +67,12 @@ internal Scp018Projectile(InventorySystem.Items.ThrowableProjectiles.Scp018Proje public float CurrentDamage => Base.CurrentDamage; /// - /// Gets or sets the + /// Gets or sets the velocity of SCP-018. /// public Vector3 Velocity { - get => PhysicsModule.Rb.velocity; - set => PhysicsModule.Rb.velocity = value; + get => PhysicsModule.Rb.linearVelocity; + set => PhysicsModule.Rb.linearVelocity = value; } /// @@ -63,7 +81,7 @@ public Vector3 Velocity /// Intensities:
/// 4-150 Low
/// 150-400 Medium
- /// 400+ High + /// 400+ High. /// ///
/// Velocity to play the sound for. @@ -76,19 +94,4 @@ internal override void OnRemove() Dictionary.Remove(Base); } - - /// - /// Gets the Scp-018 from the or creates a new one if it doesn't exist and the provided was not . - /// - /// The of the projectile. - /// The requested projectile or . - [return: NotNullIfNotNull(nameof(projectile))] - public static Scp018Projectile? Get(InventorySystem.Items.ThrowableProjectiles.Scp018Projectile? projectile) - { - if (projectile == null) - return null; - - return Dictionary.TryGetValue(projectile, out Scp018Projectile wrapper) ? wrapper : (Scp018Projectile)CreateItemWrapper(projectile); - } } - diff --git a/LabApi/Features/Wrappers/Pickups/Projectiles/Grenades/Scp2176Projectile.cs b/LabApi/Features/Wrappers/Pickups/Projectiles/Grenades/Scp2176Projectile.cs index bc32659a..71602304 100644 --- a/LabApi/Features/Wrappers/Pickups/Projectiles/Grenades/Scp2176Projectile.cs +++ b/LabApi/Features/Wrappers/Pickups/Projectiles/Grenades/Scp2176Projectile.cs @@ -1,5 +1,4 @@ -using InventorySystem.Items.ThrowableProjectiles; -using System.Collections.Generic; +using System.Collections.Generic; using System.Diagnostics.CodeAnalysis; namespace LabApi.Features.Wrappers; @@ -19,16 +18,35 @@ public class Scp2176Projectile : TimedGrenadeProjectile ///
public static new IReadOnlyCollection List => Dictionary.Values; + /// + /// Gets the Scp-2176 from the or creates a new one if it doesn't exist and the provided was not . + /// + /// The of the projectile. + /// The requested projectile or . + [return: NotNullIfNotNull(nameof(projectile))] + public static Scp2176Projectile? Get(InventorySystem.Items.ThrowableProjectiles.Scp2176Projectile? projectile) + { + if (projectile == null) + { + return null; + } + + return Dictionary.TryGetValue(projectile, out Scp2176Projectile wrapper) ? wrapper : (Scp2176Projectile)CreateItemWrapper(projectile); + } + /// /// A protected constructor to prevent external instantiation. /// /// The of the pickup. - internal Scp2176Projectile(InventorySystem.Items.ThrowableProjectiles.Scp2176Projectile projectilePickup) : base(projectilePickup) + internal Scp2176Projectile(InventorySystem.Items.ThrowableProjectiles.Scp2176Projectile projectilePickup) + : base(projectilePickup) { Base = projectilePickup; if (CanCache) + { Dictionary.Add(projectilePickup, this); + } } /// @@ -60,19 +78,4 @@ internal override void OnRemove() Dictionary.Remove(Base); } - - /// - /// Gets the Scp-2176 from the or creates a new one if it doesn't exist and the provided was not . - /// - /// The of the projectile. - /// The requested projectile or . - [return: NotNullIfNotNull(nameof(projectile))] - public static Scp2176Projectile? Get(InventorySystem.Items.ThrowableProjectiles.Scp2176Projectile? projectile) - { - if (projectile == null) - return null; - - return Dictionary.TryGetValue(projectile, out Scp2176Projectile wrapper) ? wrapper : (Scp2176Projectile)CreateItemWrapper(projectile); - } } - diff --git a/LabApi/Features/Wrappers/Pickups/Projectiles/Grenades/TimedGrenadeProjectile.cs b/LabApi/Features/Wrappers/Pickups/Projectiles/Grenades/TimedGrenadeProjectile.cs index 344d3d98..22071934 100644 --- a/LabApi/Features/Wrappers/Pickups/Projectiles/Grenades/TimedGrenadeProjectile.cs +++ b/LabApi/Features/Wrappers/Pickups/Projectiles/Grenades/TimedGrenadeProjectile.cs @@ -1,5 +1,4 @@ using Footprinting; -using Hazards; using InventorySystem; using InventorySystem.Items.Pickups; using InventorySystem.Items.ThrowableProjectiles; @@ -27,6 +26,22 @@ public class TimedGrenadeProjectile : Projectile /// public static new IReadOnlyCollection List => Dictionary.Values; + /// + /// Gets the timed grenade from the or creates a new one if it doesn't exist and the provided was not . + /// + /// The of the projectile. + /// The requested projectile or . + [return: NotNullIfNotNull(nameof(projectile))] + public static TimedGrenadeProjectile? Get(TimeGrenade? projectile) + { + if (projectile == null) + { + return null; + } + + return Dictionary.TryGetValue(projectile, out TimedGrenadeProjectile wrapper) ? wrapper : (TimedGrenadeProjectile)CreateItemWrapper(projectile); + } + /// /// Spawns a explosion particles and effect on specified location.
/// Valid for , and . Doesn't do anything for any other input. @@ -41,19 +56,23 @@ public class TimedGrenadeProjectile : Projectile /// The position to spawn the grenade on. /// Type of the grenade. /// The player owner of the grenade. - /// Time override until detonation. + /// Time override until detonation. A value less than 0 will not change the original fuse time. /// An active projectile. public static TimedGrenadeProjectile? SpawnActive(Vector3 pos, ItemType type, Player? owner = null, double timeOverride = -1d) { if (!InventoryItemLoader.TryGetItem(type, out InventorySystem.Items.ThrowableProjectiles.ThrowableItem throwable)) + { return null; + } if (throwable.Projectile is not TimeGrenade grenade) + { return null; + } TimeGrenade newPickup = GameObject.Instantiate(grenade, pos, Quaternion.identity); - PickupSyncInfo psi = new PickupSyncInfo(throwable.ItemTypeId, throwable.Weight, locked: true); + PickupSyncInfo psi = new(throwable.ItemTypeId, throwable.Weight, locked: true); newPickup.Info = psi; newPickup.PreviousOwner = new Footprint(owner?.ReferenceHub); @@ -61,7 +80,11 @@ public class TimedGrenadeProjectile : Projectile newPickup.ServerActivate(); TimedGrenadeProjectile wrapper = (TimedGrenadeProjectile)Pickup.Get(newPickup); - wrapper.RemainingTime = timeOverride; + + if (timeOverride >= 0) + { + wrapper.RemainingTime = timeOverride; + } return wrapper; } @@ -70,12 +93,15 @@ public class TimedGrenadeProjectile : Projectile /// A protected constructor to prevent external instantiation. ///
/// The of the pickup. - internal TimedGrenadeProjectile(TimeGrenade projectilePickup) : base(projectilePickup) + internal TimedGrenadeProjectile(TimeGrenade projectilePickup) + : base(projectilePickup) { Base = projectilePickup; if (CanCache) + { Dictionary.Add(projectilePickup, this); + } } /// @@ -104,19 +130,4 @@ internal override void OnRemove() Dictionary.Remove(Base); } - - /// - /// Gets the timed grenade from the or creates a new one if it doesn't exist and the provided was not . - /// - /// The of the projectile. - /// The requested projectile or . - [return: NotNullIfNotNull(nameof(projectile))] - public static TimedGrenadeProjectile? Get(TimeGrenade? projectile) - { - if (projectile == null) - return null; - - return Dictionary.TryGetValue(projectile, out TimedGrenadeProjectile wrapper) ? wrapper : (TimedGrenadeProjectile)CreateItemWrapper(projectile); - } } - diff --git a/LabApi/Features/Wrappers/Pickups/Projectiles/Projectile.cs b/LabApi/Features/Wrappers/Pickups/Projectiles/Projectile.cs index 6e9d65dd..df02aad8 100644 --- a/LabApi/Features/Wrappers/Pickups/Projectiles/Projectile.cs +++ b/LabApi/Features/Wrappers/Pickups/Projectiles/Projectile.cs @@ -21,16 +21,35 @@ public class Projectile : Pickup /// public static new IReadOnlyCollection List => Dictionary.Values; + /// + /// Gets the projectile wrapper from the or creates a new if it doesn't exist and the provided was not . + /// + /// The if the projectile. + /// The requested wrapper or . + [return: NotNullIfNotNull(nameof(projectile))] + public static Projectile? Get(ThrownProjectile? projectile) + { + if (projectile == null) + { + return null; + } + + return Dictionary.TryGetValue(projectile, out Projectile wrapper) ? wrapper : (Projectile)CreateItemWrapper(projectile); + } + /// /// A protected constructor to prevent external instantiation. /// /// The of the pickup. - protected Projectile(ThrownProjectile projectilePickup) : base(projectilePickup) + protected Projectile(ThrownProjectile projectilePickup) + : base(projectilePickup) { Base = projectilePickup; if (CanCache) + { Dictionary.Add(projectilePickup, this); + } } /// @@ -38,24 +57,11 @@ protected Projectile(ThrownProjectile projectilePickup) : base(projectilePickup) /// public new ThrownProjectile Base { get; } + /// internal override void OnRemove() { base.OnRemove(); Dictionary.Remove(Base); } - - /// - /// Gets the projectile wrapper from the or creates a new if it doesn't exist and the provided was not . - /// - /// The if the projectile. - /// The requested wrapper or . - [return: NotNullIfNotNull(nameof(projectile))] - public static Projectile? Get(ThrownProjectile? projectile) - { - if (projectile == null) - return null; - - return Dictionary.TryGetValue(projectile, out Projectile wrapper) ? wrapper : (Projectile)CreateItemWrapper(projectile); - } } diff --git a/LabApi/Features/Wrappers/Pickups/Projectiles/Scp2536Projectile.cs b/LabApi/Features/Wrappers/Pickups/Projectiles/Scp2536Projectile.cs new file mode 100644 index 00000000..e653ad9c --- /dev/null +++ b/LabApi/Features/Wrappers/Pickups/Projectiles/Scp2536Projectile.cs @@ -0,0 +1,66 @@ +using InventorySystem.Items.ThrowableProjectiles; +using System.Collections.Generic; +using System.Diagnostics.CodeAnalysis; +using BaseScp2536Projectile = InventorySystem.Items.ThrowableProjectiles.Scp2536Projectile; + +namespace LabApi.Features.Wrappers; + +/// +/// The wrapper representing Scp-2536. +/// +public class Scp2536Projectile : FlybyDetectorProjectile +{ + /// + /// Contains all the cached projectiles, accessible through their . + /// + public static new Dictionary Dictionary { get; } = []; + + /// + /// A reference to all instances of . + /// + public static new IReadOnlyCollection List => Dictionary.Values; + + /// + /// Gets the projectile wrapper from the or creates a new if it doesn't exist and the provided was not . + /// + /// The if the projectile. + /// The requested wrapper or . + [return: NotNullIfNotNull(nameof(projectile))] + public static Scp2536Projectile? Get(BaseScp2536Projectile? projectile) + { + if (projectile == null) + { + return null; + } + + return Dictionary.TryGetValue(projectile, out Scp2536Projectile wrapper) ? wrapper : (Scp2536Projectile)CreateItemWrapper(projectile); + } + + /// + /// A protected constructor to prevent external instantiation. + /// + /// The of the pickup. + internal Scp2536Projectile(BaseScp2536Projectile projectilePickup) + : base(projectilePickup) + { + Base = projectilePickup; + + if (CanCache) + { + Dictionary.Add(projectilePickup, this); + } + } + + /// + /// The of the pickup. + /// + public new BaseScp2536Projectile Base { get; } + + /// + internal override void OnRemove() + { + base.OnRemove(); + + Dictionary.Remove(Base); + } +} diff --git a/LabApi/Features/Wrappers/Pickups/Projectiles/SingleTrajectoryProjectile.cs b/LabApi/Features/Wrappers/Pickups/Projectiles/SingleTrajectoryProjectile.cs new file mode 100644 index 00000000..8e96268b --- /dev/null +++ b/LabApi/Features/Wrappers/Pickups/Projectiles/SingleTrajectoryProjectile.cs @@ -0,0 +1,66 @@ +using InventorySystem.Items.ThrowableProjectiles; +using System.Collections.Generic; +using System.Diagnostics.CodeAnalysis; +using BaseSingleTrajectoryProjectile = InventorySystem.Items.ThrowableProjectiles.SingleTrajectoryProjectile; + +namespace LabApi.Features.Wrappers; + +/// +/// The wrapper representing pre-calculated trajectory. +/// +public class SingleTrajectoryProjectile : Projectile +{ + /// + /// Contains all the cached projectiles, accessible through their . + /// + public static new Dictionary Dictionary { get; } = []; + + /// + /// A reference to all instances of . + /// + public static new IReadOnlyCollection List => Dictionary.Values; + + /// + /// Gets the projectile wrapper from the or creates a new if it doesn't exist and the provided was not . + /// + /// The if the projectile. + /// The requested wrapper or . + [return: NotNullIfNotNull(nameof(projectile))] + public static SingleTrajectoryProjectile? Get(BaseSingleTrajectoryProjectile? projectile) + { + if (projectile == null) + { + return null; + } + + return Dictionary.TryGetValue(projectile, out SingleTrajectoryProjectile wrapper) ? wrapper : (SingleTrajectoryProjectile)CreateItemWrapper(projectile); + } + + /// + /// A protected constructor to prevent external instantiation. + /// + /// The of the pickup. + internal SingleTrajectoryProjectile(BaseSingleTrajectoryProjectile projectilePickup) + : base(projectilePickup) + { + Base = projectilePickup; + + if (CanCache) + { + Dictionary.Add(projectilePickup, this); + } + } + + /// + /// The of the pickup. + /// + public new BaseSingleTrajectoryProjectile Base { get; } + + /// + internal override void OnRemove() + { + base.OnRemove(); + + Dictionary.Remove(Base); + } +} diff --git a/LabApi/Features/Wrappers/Pickups/Projectiles/SnowballProjectile.cs b/LabApi/Features/Wrappers/Pickups/Projectiles/SnowballProjectile.cs new file mode 100644 index 00000000..6f4265cb --- /dev/null +++ b/LabApi/Features/Wrappers/Pickups/Projectiles/SnowballProjectile.cs @@ -0,0 +1,65 @@ +using System.Collections.Generic; +using System.Diagnostics.CodeAnalysis; +using BaseSnowballProjectile = InventorySystem.Items.ThrowableProjectiles.SnowballProjectile; + +namespace LabApi.Features.Wrappers; + +/// +/// The wrapper representing snowball projectile. +/// +public class SnowballProjectile : FlybyDetectorProjectile +{ + /// + /// Contains all the cached projectiles, accessible through their . + /// + public static new Dictionary Dictionary { get; } = []; + + /// + /// A reference to all instances of . + /// + public static new IReadOnlyCollection List => Dictionary.Values; + + /// + /// Gets the projectile wrapper from the or creates a new if it doesn't exist and the provided was not . + /// + /// The if the projectile. + /// The requested wrapper or . + [return: NotNullIfNotNull(nameof(projectile))] + public static SnowballProjectile? Get(BaseSnowballProjectile? projectile) + { + if (projectile == null) + { + return null; + } + + return Dictionary.TryGetValue(projectile, out SnowballProjectile wrapper) ? wrapper : (SnowballProjectile)CreateItemWrapper(projectile); + } + + /// + /// A protected constructor to prevent external instantiation. + /// + /// The of the pickup. + internal SnowballProjectile(BaseSnowballProjectile projectilePickup) + : base(projectilePickup) + { + Base = projectilePickup; + + if (CanCache) + { + Dictionary.Add(projectilePickup, this); + } + } + + /// + /// The of the pickup. + /// + public new BaseSnowballProjectile Base { get; } + + /// + internal override void OnRemove() + { + base.OnRemove(); + + Dictionary.Remove(Base); + } +} diff --git a/LabApi/Features/Wrappers/Pickups/RadioPickup.cs b/LabApi/Features/Wrappers/Pickups/RadioPickup.cs index 38e35ab6..a1082b67 100644 --- a/LabApi/Features/Wrappers/Pickups/RadioPickup.cs +++ b/LabApi/Features/Wrappers/Pickups/RadioPickup.cs @@ -13,12 +13,28 @@ public class RadioPickup : Pickup /// /// Contains all the cached radio pickups, accessible through their . /// - public new static Dictionary Dictionary { get; } = []; + public static new Dictionary Dictionary { get; } = []; /// /// A reference to all instances of . /// - public new static IReadOnlyCollection List => Dictionary.Values; + public static new IReadOnlyCollection List => Dictionary.Values; + + /// + /// Gets the radio pickup from the or creates a new if it doesn't exist and the provided was not . + /// + /// The if the pickup. + /// The requested pickup or . + [return: NotNullIfNotNull(nameof(pickup))] + public static RadioPickup? Get(BaseRadioPickup? pickup) + { + if (pickup == null) + { + return null; + } + + return Dictionary.TryGetValue(pickup, out RadioPickup wrapper) ? wrapper : (RadioPickup)CreateItemWrapper(pickup); + } /// /// An internal constructor to prevent external instantiation. @@ -30,16 +46,9 @@ internal RadioPickup(BaseRadioPickup baseRadioPickup) Base = baseRadioPickup; if (CanCache) + { Dictionary.Add(baseRadioPickup, this); - } - - /// - /// A internal method to remove itself from the cache when the base object is destroyed. - /// - internal override void OnRemove() - { - base.OnRemove(); - Dictionary.Remove(Base); + } } /// @@ -65,9 +74,13 @@ public RadioMessages.RadioRangeLevel RangeLevel set { if (value == RadioMessages.RadioRangeLevel.RadioDisabled) + { IsEnabled = false; + } else + { Base.NetworkSavedRange = (byte)value; + } } } @@ -81,16 +94,11 @@ public float Battery } /// - /// Gets the radio pickup from the or creates a new if it doesn't exist and the provided was not . + /// A internal method to remove itself from the cache when the base object is destroyed. /// - /// The if the pickup. - /// The requested pickup or . - [return: NotNullIfNotNull(nameof(pickup))] - public static RadioPickup? Get(BaseRadioPickup? pickup) + internal override void OnRemove() { - if (pickup == null) - return null; - - return Dictionary.TryGetValue(pickup, out RadioPickup wrapper) ? wrapper : (RadioPickup)CreateItemWrapper(pickup); + base.OnRemove(); + Dictionary.Remove(Base); } } diff --git a/LabApi/Features/Wrappers/Pickups/Scp1576Pickup.cs b/LabApi/Features/Wrappers/Pickups/Scp1576Pickup.cs index e8b81b91..2cab477d 100644 --- a/LabApi/Features/Wrappers/Pickups/Scp1576Pickup.cs +++ b/LabApi/Features/Wrappers/Pickups/Scp1576Pickup.cs @@ -1,9 +1,5 @@ -using System; -using System.Collections.Generic; +using System.Collections.Generic; using System.Diagnostics.CodeAnalysis; -using System.Linq; -using System.Text; -using System.Threading.Tasks; using BaseScp1576Pickup = InventorySystem.Items.Usables.Scp1576.Scp1576Pickup; namespace LabApi.Features.Wrappers; @@ -16,12 +12,28 @@ public class Scp1576Pickup : Pickup /// /// Contains all the cached SCP-1576 pickups, accessible through their . /// - public new static Dictionary Dictionary { get; } = []; + public static new Dictionary Dictionary { get; } = []; /// /// A reference to all instances of . /// - public new static IReadOnlyCollection List => Dictionary.Values; + public static new IReadOnlyCollection List => Dictionary.Values; + + /// + /// Gets the SCP-1576 pickup from the or creates a new if it doesn't exist and the provided was not . + /// + /// The if the pickup. + /// The requested pickup or . + [return: NotNullIfNotNull(nameof(pickup))] + public static Scp1576Pickup? Get(BaseScp1576Pickup? pickup) + { + if (pickup == null) + { + return null; + } + + return Dictionary.TryGetValue(pickup, out Scp1576Pickup wrapper) ? wrapper : (Scp1576Pickup)CreateItemWrapper(pickup); + } /// /// An internal constructor to prevent external instantiation. @@ -33,16 +45,9 @@ internal Scp1576Pickup(BaseScp1576Pickup baseScp1576Pickup) Base = baseScp1576Pickup; if (CanCache) + { Dictionary.Add(baseScp1576Pickup, this); - } - - /// - /// A internal method to remove itself from the cache when the base object is destroyed. - /// - internal override void OnRemove() - { - base.OnRemove(); - Dictionary.Remove(Base); + } } /// @@ -60,17 +65,11 @@ public float HornPosition } /// - /// Gets the SCP-1576 pickup from the or creates a new if it doesn't exist and the provided was not . + /// A internal method to remove itself from the cache when the base object is destroyed. /// - /// The if the pickup. - /// The requested pickup or . - [return: NotNullIfNotNull(nameof(pickup))] - public static Scp1576Pickup? Get(BaseScp1576Pickup? pickup) + internal override void OnRemove() { - if (pickup == null) - return null; - - return Dictionary.TryGetValue(pickup, out Scp1576Pickup wrapper) ? wrapper : (Scp1576Pickup)CreateItemWrapper(pickup); + base.OnRemove(); + Dictionary.Remove(Base); } - } diff --git a/LabApi/Features/Wrappers/Pickups/Scp244Pickup.cs b/LabApi/Features/Wrappers/Pickups/Scp244Pickup.cs index 76b3306d..dd92874b 100644 --- a/LabApi/Features/Wrappers/Pickups/Scp244Pickup.cs +++ b/LabApi/Features/Wrappers/Pickups/Scp244Pickup.cs @@ -5,19 +5,35 @@ namespace LabApi.Features.Wrappers; /// -/// Wrapper for the +/// Wrapper for the . /// public class Scp244Pickup : Pickup { /// /// Contains all the cached SCP-244 pickups, accessible through their . /// - public new static Dictionary Dictionary { get; } = []; + public static new Dictionary Dictionary { get; } = []; /// /// A reference to all instances of . /// - public new static IReadOnlyCollection List => Dictionary.Values; + public static new IReadOnlyCollection List => Dictionary.Values; + + /// + /// Gets the SCP-244 pickup from the or creates a new if it doesn't exist and the provided was not . + /// + /// The if the pickup. + /// The requested pickup or . + [return: NotNullIfNotNull(nameof(pickup))] + public static Scp244Pickup? Get(Scp244DeployablePickup? pickup) + { + if (pickup == null) + { + return null; + } + + return Dictionary.TryGetValue(pickup, out Scp244Pickup wrapper) ? wrapper : (Scp244Pickup)CreateItemWrapper(pickup); + } /// /// An internal constructor to prevent external instantiation. @@ -29,16 +45,9 @@ internal Scp244Pickup(Scp244DeployablePickup scp244DeployablePickup) Base = scp244DeployablePickup; if (CanCache) + { Dictionary.Add(scp244DeployablePickup, this); - } - - /// - /// A internal method to remove itself from the cache when the base object is destroyed. - /// - internal override void OnRemove() - { - base.OnRemove(); - Dictionary.Remove(Base); + } } /// @@ -56,21 +65,16 @@ public Scp244State State } /// - /// Gets or set the size of the SCP-244 cloud. + /// Gets the size of the SCP-244 cloud. /// public float SizePercent => Base.CurrentSizePercent; /// - /// Gets the SCP-244 pickup from the or creates a new if it doesn't exist and the provided was not . + /// A internal method to remove itself from the cache when the base object is destroyed. /// - /// The if the pickup. - /// The requested pickup or . - [return: NotNullIfNotNull(nameof(pickup))] - public static Scp244Pickup? Get(Scp244DeployablePickup? pickup) + internal override void OnRemove() { - if (pickup == null) - return null; - - return Dictionary.TryGetValue(pickup, out Scp244Pickup wrapper) ? wrapper : (Scp244Pickup)CreateItemWrapper(pickup); + base.OnRemove(); + Dictionary.Remove(Base); } } diff --git a/LabApi/Features/Wrappers/Pickups/Scp330Pickup.cs b/LabApi/Features/Wrappers/Pickups/Scp330Pickup.cs index 5d133ed1..c3572e58 100644 --- a/LabApi/Features/Wrappers/Pickups/Scp330Pickup.cs +++ b/LabApi/Features/Wrappers/Pickups/Scp330Pickup.cs @@ -6,19 +6,35 @@ namespace LabApi.Features.Wrappers; /// -/// Wrapper for the +/// Wrapper for the . /// public class Scp330Pickup : Pickup { /// /// Contains all the cached SCP-330 pickups, accessible through their . /// - public new static Dictionary Dictionary { get; } = []; + public static new Dictionary Dictionary { get; } = []; /// /// A reference to all instances of . /// - public new static IReadOnlyCollection List => Dictionary.Values; + public static new IReadOnlyCollection List => Dictionary.Values; + + /// + /// Gets the SCP-330 pickup from the or creates a new if it doesn't exist and the provided was not . + /// + /// The if the pickup. + /// The requested pickup or . + [return: NotNullIfNotNull(nameof(pickup))] + public static Scp330Pickup? Get(BaseScp330Pickup? pickup) + { + if (pickup == null) + { + return null; + } + + return Dictionary.TryGetValue(pickup, out Scp330Pickup wrapper) ? wrapper : (Scp330Pickup)CreateItemWrapper(pickup); + } /// /// An internal constructor to prevent external instantiation. @@ -30,16 +46,9 @@ internal Scp330Pickup(BaseScp330Pickup baseScp330Pickup) Base = baseScp330Pickup; if (CanCache) + { Dictionary.Add(baseScp330Pickup, this); - } - - /// - /// A internal method to remove itself from the cache when the base object is destroyed. - /// - internal override void OnRemove() - { - base.OnRemove(); - Dictionary.Remove(Base); + } } /// @@ -63,17 +72,11 @@ public CandyKindID ExposedCandy } /// - /// Gets the SCP-330 pickup from the or creates a new if it doesn't exist and the provided was not . + /// A internal method to remove itself from the cache when the base object is destroyed. /// - /// The if the pickup. - /// The requested pickup or . - [return: NotNullIfNotNull(nameof(pickup))] - public static Scp330Pickup? Get(BaseScp330Pickup? pickup) + internal override void OnRemove() { - if (pickup == null) - return null; - - return Dictionary.TryGetValue(pickup, out Scp330Pickup wrapper) ? wrapper : (Scp330Pickup)CreateItemWrapper(pickup); + base.OnRemove(); + Dictionary.Remove(Base); } - } diff --git a/LabApi/Features/Wrappers/Pickups/TimedGrenadePickup.cs b/LabApi/Features/Wrappers/Pickups/TimedGrenadePickup.cs index 9d290f7f..c4f62cea 100644 --- a/LabApi/Features/Wrappers/Pickups/TimedGrenadePickup.cs +++ b/LabApi/Features/Wrappers/Pickups/TimedGrenadePickup.cs @@ -12,12 +12,28 @@ public class TimedGrenadePickup : Pickup /// /// Contains all the cached timed grenade pickups, accessible through their . /// - public new static Dictionary Dictionary { get; } = []; + public static new Dictionary Dictionary { get; } = []; /// /// A reference to all instances of . /// - public new static IReadOnlyCollection List => Dictionary.Values; + public static new IReadOnlyCollection List => Dictionary.Values; + + /// + /// Gets the timed grenade pickup from the or creates a new if it doesn't exist and the provided was not . + /// + /// The if the pickup. + /// The requested pickup or . + [return: NotNullIfNotNull(nameof(pickup))] + public static TimedGrenadePickup? Get(BaseTimedGrenadePickup? pickup) + { + if (pickup == null) + { + return null; + } + + return Dictionary.TryGetValue(pickup, out TimedGrenadePickup wrapper) ? wrapper : (TimedGrenadePickup)CreateItemWrapper(pickup); + } /// /// An internal constructor to prevent external instantiation. @@ -29,16 +45,9 @@ internal TimedGrenadePickup(BaseTimedGrenadePickup baseTimedGrenadePickup) Base = baseTimedGrenadePickup; if (CanCache) + { Dictionary.Add(baseTimedGrenadePickup, this); - } - - /// - /// A internal method to remove itself from the cache when the base object is destroyed. - /// - internal override void OnRemove() - { - base.OnRemove(); - Dictionary.Remove(Base); + } } /// @@ -47,16 +56,11 @@ internal override void OnRemove() public new BaseTimedGrenadePickup Base { get; } /// - /// Gets the timed grenade pickup from the or creates a new if it doesn't exist and the provided was not . + /// A internal method to remove itself from the cache when the base object is destroyed. /// - /// The if the pickup. - /// The requested pickup or . - [return: NotNullIfNotNull(nameof(pickup))] - public static TimedGrenadePickup? Get(BaseTimedGrenadePickup? pickup) + internal override void OnRemove() { - if (pickup == null) - return null; - - return Dictionary.TryGetValue(pickup, out TimedGrenadePickup wrapper) ? wrapper : (TimedGrenadePickup)CreateItemWrapper(pickup); + base.OnRemove(); + Dictionary.Remove(Base); } } diff --git a/LabApi/Features/Wrappers/Players/Player.cs b/LabApi/Features/Wrappers/Players/Player.cs index b3592af2..6f000473 100644 --- a/LabApi/Features/Wrappers/Players/Player.cs +++ b/LabApi/Features/Wrappers/Players/Player.cs @@ -8,6 +8,7 @@ using InventorySystem.Disarming; using InventorySystem.Items; using InventorySystem.Items.Pickups; +using InventorySystem.Items.Usables.Scp330; using LabApi.Features.Enums; using LabApi.Features.Stores; using MapGeneration; @@ -16,6 +17,8 @@ using NorthwoodLib.Pools; using PlayerRoles; using PlayerRoles.FirstPersonControl; +using PlayerRoles.FirstPersonControl.NetworkMessages; +using PlayerRoles.FirstPersonControl.Thirdperson.Subcontrollers; using PlayerRoles.PlayableScps.HumeShield; using PlayerRoles.Spectating; using PlayerRoles.Voice; @@ -40,14 +43,14 @@ namespace LabApi.Features.Wrappers; public class Player { /// - /// Contains all the cached players in the game, accessible through their . + /// A cache of players by their User ID. Does not necessarily contain all players. /// - public static Dictionary Dictionary { get; } = []; + private static readonly Dictionary UserIdCache = new(CustomNetworkManager.slots, StringComparer.OrdinalIgnoreCase); /// - /// A cache of players by their User ID. Does not necessarily contain all players. + /// Contains all the cached players in the game, accessible through their . /// - private static readonly Dictionary UserIdCache = new(CustomNetworkManager.slots, StringComparer.OrdinalIgnoreCase); + public static Dictionary Dictionary { get; } = []; /// /// A reference to all instances currently in the game. @@ -100,9 +103,9 @@ public class Player public static int Count => ReadyList.Count(); /// - /// Gets the amount of non-verified players + /// Gets the amount of non-verified players. /// - public static int NonVerifiedCount => ConnectionsCount - Count; + public static int NonVerifiedCount => UnauthenticatedList.Count(); /// /// Gets the amount of connected players. Regardless of their authentication status. @@ -110,962 +113,1202 @@ public class Player public static int ConnectionsCount => LiteNetLib4MirrorCore.Host.ConnectedPeersCount; /// - /// Initializes the class to subscribe to events and handle the player cache. + /// Validates the custom info text and returns result whether it is valid or invalid.
+ /// Current validation requirements are the following: + ///
+ /// + /// Match the regex. + /// Use only color,i,b and size rich text tags. + /// Colors used have to be from + /// + ///
///
- [InitializeWrapper] - internal static void Initialize() + /// The text to check on. + /// Out parameter containing rejection reason. + /// Whether is the info parameter valid. + public static bool ValidateCustomInfo(string text, out string rejectionReason) => NicknameSync.ValidateCustomInfo(text, out rejectionReason); + + /// + /// Gets a all players matching the criteria specified by the . + /// + /// The of the players to include. + /// The set of players that match the criteria. + /// + /// By default this returns the same set of players as . + /// + public static IEnumerable GetAll(PlayerSearchFlags flags = PlayerSearchFlags.AuthenticatedAndDummy) { - Dictionary.Clear(); - UserIdCache.Clear(); + bool authenticated = (flags & PlayerSearchFlags.AuthenticatedPlayers) > 0; + bool unauthenticated = (flags & PlayerSearchFlags.UnauthenticatedPlayers) > 0; + bool dummyNpcs = (flags & PlayerSearchFlags.DummyNpcs) > 0; + bool regularNpcs = (flags & PlayerSearchFlags.RegularNpcs) > 0; + bool host = (flags & PlayerSearchFlags.Host) > 0; - ReferenceHub.OnPlayerAdded += AddPlayer; - ReferenceHub.OnPlayerRemoved += RemovePlayer; + bool includePlayers = authenticated || unauthenticated; + bool allPlayers = authenticated && unauthenticated; + bool includeNpcs = dummyNpcs || regularNpcs; + bool allNpcs = dummyNpcs && regularNpcs; + + foreach (Player player in List) + { + if ((includePlayers && player.IsPlayer && (allPlayers || player.IsReady == authenticated)) || + ((includeNpcs && player.IsNpc) && (allNpcs || player.IsDummy == dummyNpcs)) || + (host && player.IsHost)) + { + yield return player; + } + } } + #region Player Getters + /// - /// An internal constructor to prevent external instantiation. + /// Gets the player wrapper from the , or creates a new one if it doesn't exist. /// /// The reference hub of the player. - internal Player(ReferenceHub referenceHub) + /// The requested player or null if the reference hub is null. + [return: NotNullIfNotNull(nameof(referenceHub))] + public static Player? Get(ReferenceHub? referenceHub) { - Dictionary.Add(referenceHub, this); + if (referenceHub == null) + { + return null; + } - ReferenceHub = referenceHub; - CustomDataStoreManager.AddPlayer(this); + return Dictionary.TryGetValue(referenceHub, out Player player) ? player : CreatePlayerWrapper(referenceHub); } /// - /// The Reference Hub of the player. + /// Gets a list of players from a list of reference hubs. /// - public ReferenceHub ReferenceHub { get; } + /// The reference hubs of the players. + /// A list of players. + public static List Get(IEnumerable referenceHubs) + { + // We rent a list from the pool to avoid unnecessary allocations. + // We don't care if the developer forgets to return the list to the pool + // as at least it will be more efficient than always allocating a new list. + List list = ListPool.Shared.Rent(); + return GetNonAlloc(referenceHubs, list); + } /// - /// Gets the player's . + /// Gets a list of players from a list of reference hubs without allocating a new list. /// - public GameObject GameObject => ReferenceHub.gameObject; + /// The reference hubs of the players. + /// A reference to the list to add the players to. + /// The passed in. + public static List GetNonAlloc(IEnumerable referenceHubs, List list) + { + // We clear the list to avoid any previous data. + list.Clear(); - /// - /// Gets whether the player is the host or server. - /// - public bool IsHost => ReferenceHub.isLocalPlayer; + // And then we add all the players to the list. + list.AddRange(referenceHubs.Select(Get)!); - /// - /// Gets whether the player is the dedicated server. - /// - [Obsolete($"Use {nameof(IsHost)} instead")] - public bool IsServer => ReferenceHub.isLocalPlayer; + // We finally return the list. + return list; + } - /// - /// Gets whether this instance is not controlled by a real human being. - /// - /// - /// This list includes dummy players. - /// - public bool IsNpc => !IsHost && ReferenceHub.connectionToClient.GetType() != typeof(NetworkConnectionToClient); + #region Get Player from a GameObject /// - /// Gets whether the player is a real player and not the host or an Npc. + /// Gets the associated with the . /// - public bool IsPlayer => Connection.GetType() == typeof(NetworkConnectionToClient); + /// The to get the player from. + /// The associated with the or null if it doesn't exist. + public static Player? Get(GameObject? gameObject) => TryGet(gameObject, out Player? player) ? player : null; /// - /// Gets whether the player is a dummy instance. + /// Tries to get the associated with the . /// - public bool IsDummy => ReferenceHub.authManager.InstanceMode == ClientInstanceMode.Dummy; + /// The to get the player from. + /// The associated with the or null if it doesn't exist. + /// Whether the player was successfully retrieved. + public static bool TryGet(GameObject? gameObject, [NotNullWhen(true)] out Player? player) + { + player = null; + if (gameObject == null) + { + return false; + } - /// - /// Gets the Player's User ID. - /// - public string UserId => ReferenceHub.authManager.UserId; + if (!ReferenceHub.TryGetHub(gameObject, out ReferenceHub? hub)) + { + return false; + } - /// - /// Gets the player's Network ID. - /// - public uint NetworkId => ReferenceHub.characterClassManager.netId; + player = Get(hub); + return true; + } - /// - /// Gets the player's . - /// - public NetworkConnection Connection => IsHost ? ReferenceHub.networkIdentity.connectionToServer : ReferenceHub.networkIdentity.connectionToClient; + #endregion - /// - /// Gets the player's value. - /// - public int PlayerId => ReferenceHub.PlayerId; + #region Get Player from a NetworkIdentity /// - /// Gets if the player is currently offline. + /// Gets the associated with the . /// - public bool IsOffline => GameObject == null; + /// The to get the player from. + /// The associated with the or null if it doesn't exist. + public static Player? Get(NetworkIdentity? identity) => TryGet(identity, out Player? player) ? player : null; /// - /// Gets if the player is currently online. + /// Tries to get the associated with the . /// - public bool IsOnline => !IsOffline; + /// The to get the player from. + /// The associated with the or null if it doesn't exist. + /// Whether the player was successfully retrieved. + public static bool TryGet(NetworkIdentity? identity, [NotNullWhen(true)] out Player? player) + { + player = null; + if (identity == null) + { + return false; + } - /// - /// Gets if the player is properly connected and authenticated. - /// - public bool IsReady => ReferenceHub.authManager.InstanceMode != ClientInstanceMode.Unverified && ReferenceHub.nicknameSync.NickSet; + if (!TryGet(identity.netId, out player)) + { + return false; + } + + return true; + } + + #endregion + + #region Get Player from a NetworkIdentity.netId (uint) /// - /// Gets the player's IP address. + /// Gets the associated with the . /// - public string IpAddress => ReferenceHub.characterClassManager.connectionToClient.address; + /// The to get the player from. + /// The associated with the or null if it doesn't exist. + public static Player? Get(uint netId) => TryGet(netId, out Player? player) ? player : null; /// - /// Gets or sets the player's current role. + /// Tries to get the associated with the . /// - public RoleTypeId Role + /// The to get the player from. + /// The associated with the or null if it doesn't exist. + /// Whether the player was successfully retrieved. + public static bool TryGet(uint netId, [NotNullWhen(true)] out Player? player) { - get => ReferenceHub.GetRoleId(); - set => ReferenceHub.roleManager.ServerSetRole(value, RoleChangeReason.RemoteAdmin); + player = null; + if (!ReferenceHub.TryGetHubNetID(netId, out ReferenceHub hub)) + { + return false; + } + + player = Get(hub); + return true; } - /// - /// Gets the player's current . - /// - public PlayerRoleBase RoleBase => ReferenceHub.roleManager.CurrentRole; + #endregion + + #region Get Player from a ICommandSender /// - /// Gets the Player's Nickname. + /// Gets the associated with the . /// - public string Nickname => ReferenceHub.nicknameSync.MyNick; + /// The to get the player from. + /// The associated with the or null if it doesn't exist. + public static Player? Get(ICommandSender? sender) => TryGet(sender, out Player? player) ? player : null; /// - /// Gets or sets the Player's Display Name. + /// Tries to get the associated with the . /// - public string DisplayName + /// The to get the player from. + /// The associated with the or null if it doesn't exist. + /// Whether the player was successfully retrieved. + public static bool TryGet(ICommandSender? sender, [NotNullWhen(true)] out Player? player) { - get => ReferenceHub.nicknameSync.DisplayName; - set => ReferenceHub.nicknameSync.DisplayName = value; + player = null; + + if (sender is not CommandSender commandSender) + { + return false; + } + + return TryGet(commandSender.SenderId, out player); } + #endregion + + #region Get Player from a UserId + /// - /// Gets the log name needed for command senders. + /// Gets the associated with the . /// - public string LogName => IsHost ? "SERVER CONSOLE" : $"{Nickname} ({UserId})"; + /// The User ID of the player. + /// The associated with the or null if it doesn't exist. + public static Player? Get(string? userId) => TryGet(userId, out Player? player) ? player : null; /// - /// Gets or sets the player's custom info.
- /// Do note that custom info is restriced by several things listed in . - /// Please use this method to validate your string as it is validated on the client by the same method. + /// Tries to get the associated with the . ///
- public string CustomInfo + /// The user ID of the player. + /// The associated with the or null if it doesn't exist. + /// Whether the player was successfully retrieved. + public static bool TryGet(string? userId, [NotNullWhen(true)] out Player? player) { - get => ReferenceHub.nicknameSync.CustomPlayerInfo; - set => ReferenceHub.nicknameSync.CustomPlayerInfo = value; + player = null; + if (string.IsNullOrEmpty(userId)) + { + return false; + } + + if (UserIdCache.TryGetValue(userId!, out player) && player.IsOnline) + { + return true; + } + + player = List.FirstOrDefault(x => x.UserId == userId); + if (player == null) + { + return false; + } + + UserIdCache[userId!] = player; + return true; } + #endregion + + #region Get Player from a Player Id + /// - /// Gets or sets the player's info area flags. - /// Flags determine what info is displayed to other players when they hover their crosshair over. + /// Gets the associated with the . /// - public PlayerInfoArea InfoArea - { - get => ReferenceHub.nicknameSync.Network_playerInfoToShow; - set => ReferenceHub.nicknameSync.Network_playerInfoToShow = value; - } + /// The player ID of the player. + /// The associated with the or null if it doesn't exist. + public static Player? Get(int playerId) => TryGet(playerId, out Player? player) ? player : null; /// - /// Gets or sets the player's current health. + /// Tries to get the associated with the . /// - public float Health + /// The player ID of the player. + /// The associated with the or null if it doesn't exist. + /// Whether the player was successfully retrieved. + public static bool TryGet(int playerId, [NotNullWhen(true)] out Player? player) { - get => ReferenceHub.playerStats.GetModule().CurValue; - set => ReferenceHub.playerStats.GetModule().CurValue = value; + player = List.FirstOrDefault(n => n.PlayerId == playerId); + return player != null; } + #endregion + + #region Get Player from a Name + /// - /// Gets or sets the player's current maximum health. + /// Get closest player by lexicographical order. + /// Players are compared by their . /// - public float MaxHealth - { - get => ReferenceHub.playerStats.GetModule().MaxValue; - set => ReferenceHub.playerStats.GetModule().MaxValue = value; - } + /// The input to search the player by. + /// Whether the full match is required. + /// Player or if no close player found. + public static Player? GetByDisplayName(string input, bool requireFullMatch = false) => GetByName(input, requireFullMatch, static p => p.DisplayName); /// - /// Gets or sets the player's current artificial health.
- /// Setting the value will clear all the current "processes" (each process is responsible for decaying AHP value separately. Eg 2 processes blue candy AHP, which doesn't decay and adrenaline proccess, where AHP does decay).
- /// Note: This value cannot be greater than . Set it to your desired value first if its over and then set this one. + /// Gets the closest player by lexicographical order. + /// Players are compared by their . ///
- public float ArtificialHealth + /// The input to search the player by. + /// Whether the full match is required. + /// Player or if no close player found. + public static Player? GetByNickname(string input, bool requireFullMatch = false) => GetByName(input, requireFullMatch, static p => p.Nickname); + + /// + /// Gets the closest player by lexicographical order. + /// Base function to allow to select by player property. + /// + /// The input to search the player by. + /// Whether the full match is required. + /// Function to select player property. + /// Player or if no close player found. + public static Player? GetByName(string input, bool requireFullMatch, Func propertySelector) { - get => ReferenceHub.playerStats.GetModule().CurValue; - set - { - AhpStat ahp = ReferenceHub.playerStats.GetModule(); - ahp.ServerKillAllProcesses(); + IOrderedEnumerable sortedPlayers = List.OrderBy(propertySelector); - if (value > 0) - ReferenceHub.playerStats.GetModule().ServerAddProcess(value, MaxArtificialHealth, 0f, 1f, 0f, false); + foreach (Player player in sortedPlayers) + { + string toCheck = propertySelector(player); + if (requireFullMatch) + { + if (toCheck.Equals(input, StringComparison.OrdinalIgnoreCase)) + { + return player; + } + } + else if (toCheck.StartsWith(input, StringComparison.OrdinalIgnoreCase)) + { + return player; + } } + + return null; } /// - /// Gets or sets the player's current maximum artificial health or hume shield.
- /// Note: The value resets to when the player's AHP reaches 0. + /// Tries to get players by name by seeing if their name starts with the input. ///
- public float MaxArtificialHealth + /// The input to search for. + /// The output players if found. + /// True if the players are found, false otherwise. + public static bool TryGetPlayersByName(string input, out List players) { - get => ReferenceHub.playerStats.GetModule().MaxValue; - set => ReferenceHub.playerStats.GetModule().MaxValue = value; + players = GetNonAlloc( + ReferenceHub.AllHubs.Where(x => x.nicknameSync.Network_myNickSync.StartsWith(input, StringComparison.OrdinalIgnoreCase)), + ListPool.Shared.Rent()); + + return players.Count > 0; } + #endregion + + #endregion + /// - /// Gets or sets the player's hume shield current value. + /// Initializes the class to subscribe to events and handle the player cache. /// - public float HumeShield + [InitializeWrapper] + internal static void Initialize() { - get => ReferenceHub.playerStats.GetModule().CurValue; - set => ReferenceHub.playerStats.GetModule().CurValue = value; + Dictionary.Clear(); + UserIdCache.Clear(); + + ReferenceHub.OnPlayerAdded += AddPlayer; + ReferenceHub.OnPlayerRemoved += RemovePlayer; } /// - /// Gets or sets the player's maximum hume shield value. - /// Note: This value may change if the player passes a new humeshield treshold for SCPs. + /// Creates a new wrapper for the player using the player's . /// - public float MaxHumeShield + /// The of the player. + /// The created player wrapper. + private static Player CreatePlayerWrapper(ReferenceHub referenceHub) { - get => ReferenceHub.playerStats.GetModule().MaxValue; - set => ReferenceHub.playerStats.GetModule().MaxValue = value; + Player player = new(referenceHub); + + if (referenceHub.isLocalPlayer) + { + Server.Host = player; + } + + return player; } /// - /// Gets or sets the current regeneration rate of the hume shield per second. - /// Returns -1 if the player's role doesn't have hume shield controller. + /// Handles the creation of a player in the server. /// - public float HumeShieldRegenRate + /// The reference hub of the player. + private static void AddPlayer(ReferenceHub referenceHub) { - get + try { - if (ReferenceHub.roleManager.CurrentRole is not IHumeShieldedRole role) - return -1; + if (Dictionary.ContainsKey(referenceHub)) + { + return; + } - return role.HumeShieldModule.HsRegeneration; + CreatePlayerWrapper(referenceHub); } - set + catch (Exception ex) { - if (ReferenceHub.roleManager.CurrentRole is not IHumeShieldedRole role) - return; - - (role.HumeShieldModule as DynamicHumeShieldController).RegenerationRate = value; + Console.Logger.InternalError($"Failed to handle player addition with exception: {ex}"); } } /// - /// Gets or sets the time that must pass after taking damage for hume shield to regenerate again. - /// Returns -1 if the player's role doesn't have hume shield controller. + /// Handles the removal of a player from the server. /// - public float HumeShieldRegenCooldown + /// The reference hub of the player. + private static void RemovePlayer(ReferenceHub referenceHub) { - get + try { - if (ReferenceHub.roleManager.CurrentRole is not IHumeShieldedRole role) - return -1; + if (referenceHub.authManager.UserId != null) + { + UserIdCache.Remove(referenceHub.authManager.UserId); + } + + if (TryGet(referenceHub.gameObject, out Player? player)) + { + CustomDataStoreManager.RemovePlayer(player); + } + + if (referenceHub.isLocalPlayer) + { + Server.Host = null; + } - return (role.HumeShieldModule as DynamicHumeShieldController).RegenerationCooldown; + Dictionary.Remove(referenceHub); } - set + catch (Exception ex) { - if (ReferenceHub.roleManager.CurrentRole is not IHumeShieldedRole role) - return; - - (role.HumeShieldModule as DynamicHumeShieldController).RegenerationCooldown = value; + Console.Logger.InternalError($"Failed to handle player removal with exception: {ex}"); } } /// - /// Gets or sets the player's current gravity. Default value is .
- /// If the player's current role is not first person controlled (inherit from then is returned.
- /// Y-axis is up and down. Negative values makes the player go down. Positive upwards. Player must not be grounded in order for gravity to take effect. + /// An internal constructor to prevent external instantiation. ///
- public Vector3 Gravity + /// The reference hub of the player. + internal Player(ReferenceHub referenceHub) { - get - { - if (ReferenceHub.roleManager.CurrentRole is IFpcRole role) - return role.FpcModule.Motor.GravityController.Gravity; + Dictionary.Add(referenceHub, this); - return Vector3.zero; - } - set - { - if (ReferenceHub.roleManager.CurrentRole is IFpcRole role) - role.FpcModule.Motor.GravityController.Gravity = value; - } + ReferenceHub = referenceHub; + CustomDataStoreManager.AddPlayer(this); } /// - /// Gets a value indicating whether the player has remote admin access. + /// The Reference Hub of the player. /// - public bool RemoteAdminAccess => ReferenceHub.serverRoles.RemoteAdmin; + public ReferenceHub ReferenceHub { get; } /// - /// Gets a value indicating whether the player has Do-Not-Track enabled. + /// Gets the player's . /// - public bool DoNotTrack => ReferenceHub.authManager.DoNotTrack; + public GameObject? GameObject => ReferenceHub ? ReferenceHub.gameObject : null; /// - /// Gets or sets a value indicating whether the player is in overwatch mode. + /// Gets whether the player is the host or server. /// - public bool IsOverwatchEnabled - { - get => ReferenceHub.serverRoles.IsInOverwatch; - set => ReferenceHub.serverRoles.IsInOverwatch = value; - } + public bool IsHost => ReferenceHub.isLocalPlayer; /// - /// Gets the player this player is currently spectating.
- /// Returns null if current player is not spectator or the spectated player is not valid. + /// Gets whether the player is the dedicated server. ///
- public Player? CurrentlySpectating - { - get - { - if (RoleBase is not SpectatorRole sr) - return null; - - if (!ReferenceHub.TryGetHubNetID(sr.SyncedSpectatedNetId, out ReferenceHub hub)) - return null; - - return Get(hub); - } - } + [Obsolete($"Use {nameof(IsHost)} instead")] + public bool IsServer => ReferenceHub.isLocalPlayer; /// - /// Gets a pooled list of players who are currently spectating this player. + /// Gets whether this instance is not controlled by a real human being. /// - public List CurrentSpectators - { - get - { - List list = ListPool.Shared.Rent(); - foreach (Player player in List) - { - if (ReferenceHub.IsSpectatedBy(player.ReferenceHub)) - list.Add(player); - } - - return list; - } - } + /// + /// This list includes dummy players. + /// + public bool IsNpc => !IsHost && ReferenceHub.connectionToClient.GetType() != typeof(NetworkConnectionToClient); /// - /// Gets or sets the player's current item. + /// Gets whether the player is a real player and not the host or an Npc. /// - public Item? CurrentItem - { - get => Item.Get(Inventory.CurInstance); - set - { - if (value == null || value.Type == ItemType.None) - Inventory.ServerSelectItem(0); - else - Inventory.ServerSelectItem(value.Serial); - } - } + public bool IsPlayer => Connection.GetType() == typeof(NetworkConnectionToClient); /// - /// Gets the player's currently active status effects. + /// Gets whether the player is a dummy instance. /// - public IEnumerable ActiveEffects => ReferenceHub.playerEffectsController.AllEffects.Where(x => x.Intensity > 0); + public bool IsDummy => ReferenceHub.authManager.InstanceMode == ClientInstanceMode.Dummy; /// - /// Gets the at the player's current position. + /// Gets the Player's User ID. /// - public Room? Room => Room.GetRoomAtPosition(Position); + public string UserId => ReferenceHub.authManager.UserId; /// - /// Gets the for the player's current room. Returns if the room is null. + /// Gets the player's Network ID. /// - public FacilityZone Zone => Room?.Zone ?? FacilityZone.None; + public uint NetworkId => ReferenceHub.characterClassManager.netId; /// - /// Gets the items in the player's inventory. + /// Gets the player's . /// - public IEnumerable Items => Inventory.UserInventory.Items.Values.Select(Item.Get)!; + public NetworkConnection Connection => IsHost ? ReferenceHub.networkIdentity.connectionToServer : ReferenceHub.networkIdentity.connectionToClient; /// - /// Gets the player's Reserve Ammo. + /// Gets the player's . /// - public Dictionary Ammo => Inventory.UserInventory.ReserveAmmo; + public NetworkConnectionToClient ConnectionToClient => ReferenceHub.networkIdentity.connectionToClient; /// - /// Gets or sets the player's group color. + /// Gets the player's value. /// - public string GroupColor - { - get => ReferenceHub.serverRoles.Network_myColor; - set => ReferenceHub.serverRoles.SetColor(value); - } + public int PlayerId => ReferenceHub.PlayerId; /// - /// Gets or sets what is displayed for the player's group. + /// Gets if the player is currently offline. /// - public string GroupName - { - get => ReferenceHub.serverRoles.Network_myText; - set => ReferenceHub.serverRoles.SetText(value); - } + [Obsolete("Use IsDestroyed instead.")] + public bool IsOffline => GameObject == null; /// - /// Gets or sets the player's . + /// Gets if the player is currently online. /// - public UserGroup? UserGroup - { - get => ReferenceHub.serverRoles.Group; - set => ReferenceHub.serverRoles.SetGroup(value); - } + [Obsolete("Use !IsDestroyed instead.")] + public bool IsOnline => !IsOffline; /// - /// Gets the player's default permission group name. Or null if the player is not in a group. + /// Gets whether the player was destroyed. /// - public string? PermissionsGroupName => ServerStatic.PermissionsHandler.Members.GetValueOrDefault(UserId); - - /// s - /// Gets the player's unit ID, or -1 if the role is not a . - /// - public int UnitId => RoleBase is HumanRole humanRole ? humanRole.UnitNameId : -1; + public bool IsDestroyed => !ReferenceHub; /// - /// Gets a value indicating whether the player has a reserved slot. + /// Gets if the player is properly connected and authenticated. /// - public bool HasReservedSlot => ReservedSlot.HasReservedSlot(UserId); + public bool IsReady => ReferenceHub.authManager.InstanceMode != ClientInstanceMode.Unverified && ReferenceHub.nicknameSync.NickSet; /// - /// Gets the player's velocity. + /// Gets the player's IP address. /// - public Vector3 Velocity => ReferenceHub.GetVelocity(); + public string IpAddress => ReferenceHub.characterClassManager.connectionToClient.address; /// - /// Gets the player's . + /// Gets or sets the player's current role. /// - public Inventory Inventory => ReferenceHub.inventory; + public RoleTypeId Role + { + get => ReferenceHub.GetRoleId(); + set => ReferenceHub.roleManager.ServerSetRole(value, RoleChangeReason.RemoteAdmin); + } /// - /// Gets the for the player, or null if the player does not have a voice module. + /// Gets the player's current . /// - public VoiceModuleBase? VoiceModule => RoleBase is IVoiceRole voiceRole ? voiceRole.VoiceModule : null; + public PlayerRoleBase RoleBase => ReferenceHub.roleManager.CurrentRole; /// - /// Gets the current for the player, or if the player is not using a voice module. + /// Get's the player's current role unique identifier. /// - public VoiceChatChannel VoiceChannel => VoiceModule?.CurrentChannel ?? VoiceChatChannel.None; + public int LifeId => RoleBase.UniqueLifeIdentifier; /// - /// Gets a value indicating whether the player has no items in their inventory. + /// Gets the Player's Nickname. /// - public bool IsWithoutItems => Inventory.UserInventory.Items.Count == 0; + public string Nickname => ReferenceHub.nicknameSync.MyNick; /// - /// Gets a value indicating whether the player's inventory is full. + /// Gets or sets the Player's Display Name. /// - public bool IsInventoryFull => Inventory.UserInventory.Items.Count >= Inventory.MaxSlots; + public string DisplayName + { + get => ReferenceHub.nicknameSync.DisplayName; + set => ReferenceHub.nicknameSync.DisplayName = value; + } /// - /// Gets a value indicating whether the player is out of ammunition. + /// Gets the log name needed for command senders. /// - public bool IsOutOfAmmo => Inventory.UserInventory.ReserveAmmo.All(ammo => ammo.Value == 0); + public string LogName => IsHost ? "SERVER CONSOLE" : $"{Nickname} ({UserId})"; /// - /// Gets or sets a value indicating whether the player is disarmed. + /// Gets or sets the player's custom info.
+ /// Do note that custom info is restricted by several things listed in . + /// Please use this method to validate your string as it is validated on the client by the same method. ///
- public bool IsDisarmed + public string CustomInfo { - get => Inventory.IsDisarmed(); - set - { - if (value) - { - Inventory.SetDisarmedStatus(null); - DisarmedPlayers.Entries.Add(new DisarmedPlayers.DisarmedEntry(ReferenceHub.networkIdentity.netId, 0U)); - new DisarmedPlayersListMessage(DisarmedPlayers.Entries).SendToAuthenticated(); - return; - } - - Inventory.SetDisarmedStatus(null); - new DisarmedPlayersListMessage(DisarmedPlayers.Entries).SendToAuthenticated(); - } + get => ReferenceHub.nicknameSync.CustomPlayerInfo; + set => ReferenceHub.nicknameSync.CustomPlayerInfo = value; } /// - /// Gets a value indicating whether the player is muted. - /// - public bool IsMuted => VoiceChatMutes.QueryLocalMute(UserId); - - /// - /// Gets a value indicating whether the player is muted from the intercom. + /// Gets or sets the player's info area flags. + /// Flags determine what info is displayed to other players when they hover their cross-hair over. /// - public bool IsIntercomMuted => VoiceChatMutes.QueryLocalMute(UserId, true); + public PlayerInfoArea InfoArea + { + get => ReferenceHub.nicknameSync.Network_playerInfoToShow; + set => ReferenceHub.nicknameSync.Network_playerInfoToShow = value; + } /// - /// Gets a value indicating whether the player is talking through a radio. + /// Gets or sets the player's current health. /// - public bool IsUsingRadio => PersonalRadioPlayback.IsTransmitting(ReferenceHub); + public float Health + { + get => ReferenceHub.playerStats.GetModule().CurValue; + set => ReferenceHub.playerStats.GetModule().CurValue = value; + } /// - /// Gets a value indicating whether the player is speaking. + /// Gets or sets the player's current maximum health. /// - public bool IsSpeaking => VoiceModule != null && VoiceModule.IsSpeaking; + public float MaxHealth + { + get => ReferenceHub.playerStats.GetModule().MaxValue; + set => ReferenceHub.playerStats.GetModule().MaxValue = value; + } /// - /// Gets a value indicating whether the player is a Global Moderator. + /// Gets or sets the player's current artificial health.
+ /// Setting the value will clear all the current "processes" (each process is responsible for decaying AHP value separately. E.g 2 processes blue candy AHP, which doesn't decay and adrenaline process, where AHP does decay).
+ /// Note: This value cannot be greater than . Set it to your desired value first if its over and then set this one. ///
- public bool IsGlobalModerator => ReferenceHub.authManager.RemoteAdminGlobalAccess; + public float ArtificialHealth + { + get => ReferenceHub.playerStats.GetModule().CurValue; + set + { + AhpStat ahp = ReferenceHub.playerStats.GetModule(); + ahp.ServerKillAllProcesses(); - /// - /// Gets a value indicating whether the player is a Northwood Staff member. - /// - public bool IsNorthwoodStaff => ReferenceHub.authManager.NorthwoodStaff; + if (value > 0) + { + ReferenceHub.playerStats.GetModule().ServerAddProcess(value, MaxArtificialHealth, 0f, 1f, 0f, false); + } + } + } /// - /// Gets or sets a value indicating whether bypass mode is enabled for the player, allowing them to open doors/gates without keycards. + /// Gets or sets the player's current maximum artificial health or hume shield.
+ /// Note: The value resets to when the player's AHP reaches 0. ///
- public bool IsBypassEnabled + public float MaxArtificialHealth { - get => ReferenceHub.serverRoles.BypassMode; - set => ReferenceHub.serverRoles.BypassMode = value; + get => ReferenceHub.playerStats.GetModule().MaxValue; + set => ReferenceHub.playerStats.GetModule().MaxValue = value; } /// - /// Gets or sets a value indicating whether god mode is enabled for the player. + /// Gets or sets the player's hume shield current value. /// - public bool IsGodModeEnabled + public float HumeShield { - get => ReferenceHub.characterClassManager.GodMode; - set => ReferenceHub.characterClassManager.GodMode = value; + get => ReferenceHub.playerStats.GetModule().CurValue; + set => ReferenceHub.playerStats.GetModule().CurValue = value; } /// - /// Gets or sets a value indicating whether noclip mode is enabled for the player. + /// Gets or sets the player's maximum hume shield value. + /// Note: This value may change if the player passes a new hume shield threshold for SCPs. /// - public bool IsNoclipEnabled + public float MaxHumeShield { - get => ReferenceHub.playerStats.GetModule().HasFlag(AdminFlags.Noclip); - set => ReferenceHub.playerStats.GetModule().SetFlag(AdminFlags.Noclip, value); + get => ReferenceHub.playerStats.GetModule().MaxValue; + set => ReferenceHub.playerStats.GetModule().MaxValue = value; } /// - /// Gets or sets the player who disarmed this player. + /// Gets or sets the current regeneration rate of the hume shield per second. + /// Returns -1 if the player's role doesn't have hume shield controller. /// - public Player? DisarmedBy + public float HumeShieldRegenRate { get { - if (!IsDisarmed) return null; - - DisarmedPlayers.DisarmedEntry entry = DisarmedPlayers.Entries.Find(x => x.DisarmedPlayer == NetworkId); + if (ReferenceHub.roleManager.CurrentRole is not IHumeShieldedRole role) + { + return -1; + } - return Get(entry.Disarmer); + return role.HumeShieldModule.HsRegeneration; } + set { - Inventory.SetDisarmedStatus(null); - - if (value == null) + if (ReferenceHub.roleManager.CurrentRole is not IHumeShieldedRole role) + { return; + } - DisarmedPlayers.Entries.Add(new DisarmedPlayers.DisarmedEntry(NetworkId, value.NetworkId)); - new DisarmedPlayersListMessage(DisarmedPlayers.Entries).SendToAuthenticated(); + ((DynamicHumeShieldController)role.HumeShieldModule).RegenerationRate = value; } } /// - /// Gets the player's current . + /// Gets or sets the time that must pass after taking damage for hume shield to regenerate again. + /// Returns -1 if the player's role doesn't have hume shield controller. /// - public Team Team => RoleBase.Team; + public float HumeShieldRegenCooldown + { + get + { + if (ReferenceHub.roleManager.CurrentRole is not IHumeShieldedRole role) + { + return -1; + } - /// - /// Gets whether the player is currently Alive. - /// - public bool IsAlive => Team != Team.Dead; + return ((DynamicHumeShieldController)role.HumeShieldModule).RegenerationCooldown; + } - /// - /// Gets if the player is an SCP. - /// - public bool IsSCP => Team == Team.SCPs; + set + { + if (ReferenceHub.roleManager.CurrentRole is not IHumeShieldedRole role) + { + return; + } - /// - /// Gets if the player is a human. - /// - public bool IsHuman => IsAlive && !IsSCP; + ((DynamicHumeShieldController)role.HumeShieldModule).RegenerationCooldown = value; + } + } /// - /// Gets if the player is part of the NTF. + /// Gets or sets the player's current gravity. Default value is .
+ /// If the player's current role is not first person controlled (inherit from then is returned.
+ /// Y-axis is up and down. Negative values makes the player go down. Positive upwards. Player must not be grounded in order for gravity to take effect. ///
- public bool IsNTF => Team == Team.FoundationForces; + public Vector3 Gravity + { + get + { + if (ReferenceHub.roleManager.CurrentRole is IFpcRole role) + { + return role.FpcModule.Motor.GravityController.Gravity; + } - /// - /// Gets if the player is part of the Chaos Insurgency. - /// - public bool IsChaos => Team == Team.ChaosInsurgency; + return Vector3.zero; + } + + set + { + if (ReferenceHub.roleManager.CurrentRole is IFpcRole role) + { + role.FpcModule.Motor.GravityController.Gravity = value; + } + } + } /// - /// Gets if the player is a tutorial. + /// Gets a value indicating whether the player has remote admin access. /// - public bool IsTutorial => Role == RoleTypeId.Tutorial; + public bool RemoteAdminAccess => ReferenceHub.serverRoles.RemoteAdmin; /// - /// Gets the player's Camera . + /// Gets a value indicating whether the player has Do-Not-Track enabled. /// - public Transform Camera => ReferenceHub.PlayerCameraReference; + public bool DoNotTrack => ReferenceHub.authManager.DoNotTrack; /// - /// Gets or sets the player's position.
- /// Returns if the player's role is not currently derived from . + /// Gets or sets a value indicating whether the player is in overwatch mode. ///
- public Vector3 Position + public bool IsOverwatchEnabled { - get - { - if (RoleBase is not IFpcRole fpcRole) - return Vector3.zero; - - return fpcRole.FpcModule.Position; - } - set => ReferenceHub.TryOverridePosition(value); + get => ReferenceHub.serverRoles.IsInOverwatch; + set => ReferenceHub.serverRoles.IsInOverwatch = value; } /// - /// Gets or sets the player's rotation. + /// Gets the player this player is currently spectating.
+ /// Returns null if current player is not spectator or the spectated player is not valid. ///
- public Quaternion Rotation + public Player? CurrentlySpectating { - get => GameObject.transform.rotation; - set => ReferenceHub.TryOverrideRotation(value.eulerAngles); + get + { + if (RoleBase is not SpectatorRole sr) + { + return null; + } + + if (!ReferenceHub.TryGetHubNetID(sr.SyncedSpectatedNetId, out ReferenceHub hub)) + { + return null; + } + + return Get(hub); + } } /// - /// Gets or sets the player's look rotation. X is vertical axis while Y is horizontal. Vertical axis is clamped by the base game logic.
- /// Returns if the player's role is not currently derived from . + /// Gets a pooled list of players who are currently spectating this player. ///
- public Vector2 LookRotation + public List CurrentSpectators { get { - if (ReferenceHub.roleManager.CurrentRole is not IFpcRole fpcRole) - return Vector2.zero; + List list = ListPool.Shared.Rent(); + foreach (Player player in List) + { + if (ReferenceHub.IsSpectatedBy(player.ReferenceHub)) + { + list.Add(player); + } + } - FpcMouseLook mouseLook = fpcRole.FpcModule.MouseLook; - return new Vector2(mouseLook.CurrentVertical, mouseLook.CurrentHorizontal); + return list; } - set => ReferenceHub.TryOverrideRotation(value); } /// - /// Gets or sets player's scale. Player's role must be for it to take effect.
- /// Vertical scale is not linear as the model's origin and scaling is done from player's feet. + /// Gets or sets whether this player can be spectated by other players. ///
- public Vector3 Scale + /// + /// This property is reset when player leaves. + /// + public bool IsSpectatable { - get - { - if (ReferenceHub.roleManager.CurrentRole is not IFpcRole fpcRole) - return Vector3.zero; + get => !SpectatableVisibilityManager.IsHidden(ReferenceHub); + set => SpectatableVisibilityManager.SetHidden(ReferenceHub, !value); + } - return fpcRole.FpcModule.Motor.ScaleController.Scale; - } + /// + /// Gets or sets the player's current item. + /// + public Item? CurrentItem + { + get => Item.Get(Inventory.CurInstance); set { - if (ReferenceHub.roleManager.CurrentRole is not IFpcRole fpcRole) - return; - - fpcRole.FpcModule.Motor.ScaleController.Scale = value; + if (value == null || value.Type == ItemType.None) + { + Inventory.ServerSelectItem(0); + } + else + { + Inventory.ServerSelectItem(value.Serial); + } } } /// - /// Gets or sets player's remaining stamina (min = 0, max = 1). + /// Gets the player's currently active status effects. /// - public float StaminaRemaining - { - get => ReferenceHub.playerStats.GetModule().CurValue; - set => ReferenceHub.playerStats.GetModule().CurValue = value; - } + public IEnumerable ActiveEffects => ReferenceHub.playerEffectsController.AllEffects.Where(static x => x.Intensity > 0); /// - /// Validates the custom info text and returns result whether it is valid or invalid.
- /// Current validation requirements are the following: - /// - /// - /// Match the regex. - /// Use only color,i,b and size rich text tags. - /// Colors used have to be from - /// - /// + /// Gets the at the player's current position. + /// May be if the player is in the void. + /// + /// Player inside of the elevator is consider to be in the said room until the elevator teleports to the next door. + /// ///
- /// The text to check on. - /// Out parameter containing rejection reason. - /// Whether is the info parameter valid. - public static bool ValidateCustomInfo(string text, out string rejectionReason) => NicknameSync.ValidateCustomInfo(text, out rejectionReason); + public Room? Room => Room.TryGetRoomAtPosition(Position, out Room? room) ? room : null; /// - /// Gets a all players matching the criteria specified by the . + /// Gets the cached room of the player. Cached room is revalidated once every frame or when player teleports.
+ /// It is not guarantee that the will match the exact same room it should be in due to the caching.
+ /// May be if the player is in the void. ///
- /// The of the players to include. - /// The set of players that match the criteria. - /// - /// By default this returns the same set of players as . - /// - public static IEnumerable GetAll(PlayerSearchFlags flags = PlayerSearchFlags.AuthenticatedAndDummy) - { - bool authenticated = (flags & PlayerSearchFlags.AuthenticatedPlayers) > 0; - bool unauthenticated = (flags & PlayerSearchFlags.UnauthenticatedPlayers) > 0; - bool dummyNpcs = (flags & PlayerSearchFlags.DummyNpcs) > 0; - bool regularNpcs = (flags & PlayerSearchFlags.RegularNpcs) > 0; - bool host = (flags & PlayerSearchFlags.Host) > 0; + public Room? CachedRoom => ReferenceHub.TryGetCurrentRoom(out RoomIdentifier rid) ? Room.Get(rid) : null; - bool includePlayers = authenticated || unauthenticated; - bool allPlayers = authenticated && unauthenticated; - bool includeNpcs = dummyNpcs || regularNpcs; - bool allNpcs = dummyNpcs && regularNpcs; + /// + /// Gets the for the player's current room. Returns if the room is null. + /// + public FacilityZone Zone => Room?.Zone ?? FacilityZone.None; - foreach (Player player in List) - { - if ((includePlayers && player.IsPlayer && (allPlayers || player.IsReady == authenticated)) || - (includeNpcs && player.IsNpc) && (allNpcs || player.IsDummy == dummyNpcs) || - (host && player.IsHost)) - yield return player; - } - } + /// + /// Gets the items in the player's inventory. + /// + public IEnumerable Items => Inventory.UserInventory.Items.Values.Select(Item.Get)!; - #region Player Getters + /// + /// Gets the player's Reserve Ammo. + /// + public Dictionary Ammo => Inventory.UserInventory.ReserveAmmo; /// - /// Gets the player wrapper from the , or creates a new one if it doesn't exist. + /// Gets or sets the player's group color. /// - /// The reference hub of the player. - /// The requested player or null if the reference hub is null. - [return: NotNullIfNotNull(nameof(referenceHub))] - public static Player? Get(ReferenceHub? referenceHub) + public string GroupColor { - if (referenceHub == null) - return null; - - return Dictionary.TryGetValue(referenceHub, out Player player) ? player : new Player(referenceHub); + get => ReferenceHub.serverRoles.Network_myColor; + set => ReferenceHub.serverRoles.SetColor(value); } /// - /// Gets a list of players from a list of reference hubs. + /// Gets or sets what is displayed for the player's group. /// - /// The reference hubs of the players. - /// A list of players. - public static List Get(IEnumerable referenceHubs) + public string GroupName { - // We rent a list from the pool to avoid unnecessary allocations. - // We don't care if the developer forgets to return the list to the pool - // as at least it will be more efficient than always allocating a new list. - List list = ListPool.Shared.Rent(); - return GetNonAlloc(referenceHubs, list); + get => ReferenceHub.serverRoles.Network_myText; + set => ReferenceHub.serverRoles.SetText(value); } /// - /// Gets a list of players from a list of reference hubs without allocating a new list. + /// Gets or sets the player's . /// - /// The reference hubs of the players. - /// A reference to the list to add the players to. - public static List GetNonAlloc(IEnumerable referenceHubs, List list) + public UserGroup? UserGroup { - // We clear the list to avoid any previous data. - list.Clear(); - // And then we add all the players to the list. - list.AddRange(referenceHubs.Select(Get)); - // We finally return the list. - return list; + get => ReferenceHub.serverRoles.Group; + set => ReferenceHub.serverRoles.SetGroup(value); } - #region Get Player from a GameObject + /// + /// Gets the player's default permission group name. Or null if the player is not in a group. + /// + public string? PermissionsGroupName => ServerStatic.PermissionsHandler.Members.GetValueOrDefault(UserId); + + /// s + /// Gets the player's unit ID, or -1 if the role is not a . + /// + public int UnitId => RoleBase is HumanRole humanRole ? humanRole.UnitNameId : -1; /// - /// Gets the associated with the . + /// Gets a value indicating whether the player has a reserved slot. /// - /// The to get the player from. - /// The associated with the or null if it doesn't exist. - public static Player? Get(GameObject? gameObject) => TryGet(gameObject, out Player? player) ? player : null; + public bool HasReservedSlot => ReservedSlot.HasReservedSlot(UserId); /// - /// Tries to get the associated with the . + /// Gets the player's velocity. /// - /// The to get the player from. - /// The associated with the or null if it doesn't exist. - /// Whether the player was successfully retrieved. - public static bool TryGet(GameObject? gameObject, [NotNullWhen(true)] out Player? player) - { - player = null; - if (gameObject == null) - return false; + public Vector3 Velocity => ReferenceHub.GetVelocity(); - if (!ReferenceHub.TryGetHub(gameObject, out ReferenceHub? hub)) - return false; + /// + /// Gets the player's . + /// + public Inventory Inventory => ReferenceHub.inventory; - player = Get(hub); - return true; + /// + /// Gets the for the player, or null if the player does not have a voice module. + /// + public VoiceModuleBase? VoiceModule => RoleBase is IVoiceRole voiceRole ? voiceRole.VoiceModule : null; + + /// + /// Gets the current for the player, or if the player is not using a voice module. + /// + public VoiceChatChannel VoiceChannel => VoiceModule?.CurrentChannel ?? VoiceChatChannel.None; + + /// + /// Gets a value indicating whether the player has no items in their inventory. + /// + public bool IsWithoutItems => Inventory.UserInventory.Items.Count == 0; + + /// + /// Gets a value indicating whether the player's inventory is full. + /// + public bool IsInventoryFull => Inventory.UserInventory.Items.Count >= Inventory.MaxSlots; + + /// + /// Gets a value indicating whether the player is out of ammunition. + /// + public bool IsOutOfAmmo => Inventory.UserInventory.ReserveAmmo.All(ammo => ammo.Value == 0); + + /// + /// Gets or sets a value indicating whether the player is disarmed. + /// + public bool IsDisarmed + { + get => Inventory.IsDisarmed(); + set + { + if (value) + { + Inventory.SetDisarmedStatus(null); + DisarmedPlayers.Entries.Add(new DisarmedPlayers.DisarmedEntry(ReferenceHub.networkIdentity.netId, 0U)); + new DisarmedPlayersListMessage(DisarmedPlayers.Entries).SendToAuthenticated(); + return; + } + + Inventory.SetDisarmedStatus(null); + new DisarmedPlayersListMessage(DisarmedPlayers.Entries).SendToAuthenticated(); + } } - #endregion + /// + /// Gets a value indicating whether the player is muted. + /// + public bool IsMuted => VoiceChatMutes.IsMuted(ReferenceHub); - #region Get Player from a NetworkIdentity + /// + /// Gets a value indicating whether the player is muted from the intercom. + /// + public bool IsIntercomMuted => VoiceChatMutes.IsMuted(ReferenceHub, true); /// - /// Gets the associated with the . + /// Gets a value indicating whether the player is talking through a radio. /// - /// The to get the player from. - /// The associated with the or null if it doesn't exist. - public static Player? Get(NetworkIdentity? identity) => TryGet(identity, out Player? player) ? player : null; + public bool IsUsingRadio => PersonalRadioPlayback.IsTransmitting(ReferenceHub); /// - /// Tries to get the associated with the . + /// Gets a value indicating whether the player is speaking. /// - /// The to get the player from. - /// The associated with the or null if it doesn't exist. - /// Whether the player was successfully retrieved. - public static bool TryGet(NetworkIdentity? identity, [NotNullWhen(true)] out Player? player) + public bool IsSpeaking => VoiceModule != null && VoiceModule.IsSpeaking; + + /// + /// Gets a value indicating whether the player is a Global Moderator. + /// + public bool IsGlobalModerator => ReferenceHub.authManager.RemoteAdminGlobalAccess; + + /// + /// Gets a value indicating whether the player is a Northwood Staff member. + /// + public bool IsNorthwoodStaff => ReferenceHub.authManager.NorthwoodStaff; + + /// + /// Gets or sets a value indicating whether bypass mode is enabled for the player, allowing them to open doors/gates without keycards. + /// + public bool IsBypassEnabled { - player = null; - if (identity == null) - return false; + get => ReferenceHub.serverRoles.BypassMode; + set => ReferenceHub.serverRoles.BypassMode = value; + } - if (!TryGet(identity.netId, out player)) - return false; + /// + /// Gets or sets a value indicating whether god mode is enabled for the player. + /// + public bool IsGodModeEnabled + { + get => ReferenceHub.characterClassManager.GodMode; + set => ReferenceHub.characterClassManager.GodMode = value; + } - return true; + /// + /// Gets or sets a value indicating whether noclip mode is enabled for the player. + /// + public bool IsNoclipEnabled + { + get => ReferenceHub.playerStats.GetModule().HasFlag(AdminFlags.Noclip); + set => ReferenceHub.playerStats.GetModule().SetFlag(AdminFlags.Noclip, value); } - #endregion + /// + /// Gets or sets the player who disarmed this player. + /// + public Player? DisarmedBy + { + get + { + if (!IsDisarmed) + { + return null; + } - #region Get Player from a NetworkIdentity.netId (uint) + DisarmedPlayers.DisarmedEntry entry = DisarmedPlayers.Entries.Find(x => x.DisarmedPlayer == NetworkId); + + return Get(entry.Disarmer); + } + + set + { + Inventory.SetDisarmedStatus(null); + + if (value == null) + { + return; + } + + DisarmedPlayers.Entries.Add(new DisarmedPlayers.DisarmedEntry(NetworkId, value.NetworkId)); + new DisarmedPlayersListMessage(DisarmedPlayers.Entries).SendToAuthenticated(); + } + } + + /// + /// Gets the player's current . + /// + public Team Team => RoleBase.Team; + + /// + /// Gets the player's current . + /// + public Faction Faction => Team.GetFaction(); + + /// + /// Gets whether the player is currently Alive. + /// + public bool IsAlive => Team != Team.Dead; /// - /// Gets the associated with the . + /// Gets if the player is an SCP. /// - /// The to get the player from. - /// The associated with the or null if it doesn't exist. - public static Player? Get(uint netId) => TryGet(netId, out Player? player) ? player : null; + public bool IsSCP => Team == Team.SCPs; /// - /// Tries to get the associated with the . + /// Gets if the player is a human. /// - /// The to get the player from. - /// The associated with the or null if it doesn't exist. - /// Whether the player was successfully retrieved. - public static bool TryGet(uint netId, [NotNullWhen(true)] out Player? player) - { - player = null; - if (!ReferenceHub.TryGetHubNetID(netId, out ReferenceHub hub)) - return false; + public bool IsHuman => IsAlive && !IsSCP; - player = Get(hub); - return true; - } + /// + /// Gets if the player is part of the NTF. + /// + public bool IsNTF => Team == Team.FoundationForces; - #endregion + /// + /// Gets if the player is part of the Chaos Insurgency. + /// + public bool IsChaos => Team == Team.ChaosInsurgency; - #region Get Player from a ICommandSender + /// + /// Gets if the player is a tutorial. + /// + public bool IsTutorial => Role == RoleTypeId.Tutorial; /// - /// Gets the associated with the . + /// Gets the player's Camera . /// - /// The to get the player from. - /// The associated with the or null if it doesn't exist. - public static Player? Get(ICommandSender? sender) => TryGet(sender, out Player? player) ? player : null; + public Transform Camera => ReferenceHub.PlayerCameraReference; /// - /// Tries to get the associated with the . + /// Gets or sets the player's position.
+ /// Returns if the player's role is not currently derived from . ///
- /// The to get the player from. - /// The associated with the or null if it doesn't exist. - /// Whether the player was successfully retrieved. - public static bool TryGet(ICommandSender? sender, [NotNullWhen(true)] out Player? player) + public Vector3 Position { - player = null; - - if (sender is not CommandSender commandSender) - return false; + get + { + if (RoleBase is not IFpcRole fpcRole) + { + return Vector3.zero; + } - return TryGet(commandSender.SenderId, out player); + return fpcRole.FpcModule.Position; + } + set => ReferenceHub.TryOverridePosition(value); } - #endregion - - #region Get Player from a UserId - /// - /// Gets the associated with the . + /// Gets or sets the player's rotation. /// - /// The User ID of the player. - /// The associated with the or null if it doesn't exist. - public static Player? Get(string? userId) => TryGet(userId, out Player? player) ? player : null; + public Quaternion Rotation + { + get => GameObject.transform.rotation; + set => ReferenceHub.TryOverrideRotation(value.eulerAngles); + } /// - /// Tries to get the associated with the . + /// Gets or sets the player's look rotation. X is vertical axis while Y is horizontal. Vertical axis is clamped by the base game logic.
+ /// Returns if the player's role is not currently derived from . ///
- /// The user ID of the player. - /// The associated with the or null if it doesn't exist. - /// Whether the player was successfully retrieved. - public static bool TryGet(string? userId, [NotNullWhen(true)] out Player? player) + public Vector2 LookRotation { - player = null; - if (string.IsNullOrEmpty(userId)) - return false; - - if (UserIdCache.TryGetValue(userId!, out player) && player.IsOnline) - return true; - - player = List.FirstOrDefault(x => x.UserId == userId); - if (player == null) - return false; + get + { + if (ReferenceHub.roleManager.CurrentRole is not IFpcRole fpcRole) + { + return Vector2.zero; + } - UserIdCache[userId!] = player; - return true; + FpcMouseLook mouseLook = fpcRole.FpcModule.MouseLook; + return new Vector2(mouseLook.CurrentVertical, mouseLook.CurrentHorizontal); + } + set => ReferenceHub.TryOverrideRotation(value); } - #endregion - - #region Get Player from a Player Id - /// - /// Gets the associated with the . + /// Gets or sets player's scale. Player's role must be for it to take effect.
+ /// Vertical scale is not linear as the model's origin and scaling is done from player's feet. ///
- /// The player ID of the player. - /// The associated with the or null if it doesn't exist. - public static Player? Get(int playerId) => TryGet(playerId, out Player? player) ? player : null; + public Vector3 Scale + { + get + { + if (ReferenceHub.roleManager.CurrentRole is not IFpcRole fpcRole) + { + return Vector3.zero; + } + + return fpcRole.FpcModule.Motor.ScaleController.Scale; + } + + set + { + if (ReferenceHub.roleManager.CurrentRole is not IFpcRole fpcRole) + { + return; + } + + fpcRole.FpcModule.Motor.ScaleController.Scale = value; + } + } /// - /// Tries to get the associated with the . + /// Gets or sets player's remaining stamina (min = 0, max = 1). /// - /// The player ID of the player. - /// The associated with the or null if it doesn't exist. - /// Whether the player was successfully retrieved. - public static bool TryGet(int playerId, [NotNullWhen(true)] out Player? player) + public float StaminaRemaining { - player = List.FirstOrDefault(n => n.PlayerId == playerId); - return player != null; + get => ReferenceHub.playerStats.GetModule().CurValue; + set => ReferenceHub.playerStats.GetModule().CurValue = value; } - #endregion - - #region Get Player from a Name - /// - /// Tries to get players by name by seeing if their name starts with the input. + /// Gets or sets the current player's emotion. /// - /// The input to search for. - /// The output players if found. - /// True if the players are found, false otherwise. - public static bool TryGetPlayersByName(string input, out List players) + public EmotionPresetType Emotion { - players = GetNonAlloc(ReferenceHub.AllHubs.Where(x => x.nicknameSync.Network_myNickSync.StartsWith(input, StringComparison.OrdinalIgnoreCase)), - ListPool.Shared.Rent()); - - return players.Count > 0; + get => EmotionSync.GetEmotionPreset(ReferenceHub); + set => EmotionSync.ServerSetEmotionPreset(ReferenceHub, value); } - #endregion - - #endregion - /// /// Teleports the player by the delta location. /// @@ -1078,6 +1321,28 @@ public static bool TryGetPlayersByName(string input, out List players) /// Rotation to add to the current one. X is vertical and Y is horizontal rotation. public void Rotate(Vector2 delta) => ReferenceHub.TryOverrideRotation(LookRotation + delta); + /// + /// Forces to jump. + /// Jumping can be also adjusted via and status effects. + /// + /// Strength that the player will jump with. + public void Jump(float jumpStrength) + { + if (ReferenceHub.roleManager.CurrentRole is IFpcRole fpcRole) + { + fpcRole.FpcModule.Motor.JumpController.ForceJump(jumpStrength); + } + } + + /// + public void Jump() + { + if (ReferenceHub.roleManager.CurrentRole is IFpcRole fpcRole) + { + Jump(fpcRole.FpcModule.JumpSpeed); + } + } + /// /// Clears displayed broadcast(s). /// @@ -1107,9 +1372,13 @@ public void SendBroadcast(string message, ushort duration, Broadcast.BroadcastFl public void Mute(bool isTemporary = true) { if (isTemporary) + { VoiceChatMutes.SetFlags(ReferenceHub, VoiceChatMutes.GetFlags(ReferenceHub) | VcMuteFlags.LocalRegular); + } else + { VoiceChatMutes.IssueLocalMute(UserId); + } } /// @@ -1119,9 +1388,13 @@ public void Mute(bool isTemporary = true) public void Unmute(bool revokeMute) { if (revokeMute) + { VoiceChatMutes.RevokeLocalMute(UserId); + } else + { VoiceChatMutes.SetFlags(ReferenceHub, VoiceChatMutes.GetFlags(ReferenceHub) & ~VcMuteFlags.LocalRegular); + } } /// @@ -1131,9 +1404,13 @@ public void Unmute(bool revokeMute) public void IntercomMute(bool isTemporary = false) { if (isTemporary) + { VoiceChatMutes.SetFlags(ReferenceHub, VoiceChatMutes.GetFlags(ReferenceHub) | VcMuteFlags.LocalIntercom); + } else + { VoiceChatMutes.IssueLocalMute(UserId, true); + } } /// @@ -1143,9 +1420,13 @@ public void IntercomMute(bool isTemporary = false) public void IntercomUnmute(bool revokeMute) { if (revokeMute) + { VoiceChatMutes.RevokeLocalMute(UserId, true); + } else + { VoiceChatMutes.SetFlags(ReferenceHub, VoiceChatMutes.GetFlags(ReferenceHub) & ~VcMuteFlags.LocalIntercom); + } } /// @@ -1207,11 +1488,15 @@ public void RemoveItem(ItemType item, int maxAmount = 1) { ItemBase? itemBase = Items.ElementAt(i).Base; if (itemBase.ItemTypeId != item) + { continue; + } RemoveItem(itemBase); if (++count >= maxAmount) + { break; + } } } @@ -1244,7 +1529,9 @@ public List DropAllItems() { List items = ListPool.Shared.Rent(); foreach (Item item in Items.ToArray()) + { items.Add(DropItem(item)); + } return items; } @@ -1252,7 +1539,7 @@ public List DropAllItems() /// /// Sets the ammo amount of a specific ammo type. /// - /// The type of ammo + /// The type of ammo. /// The amount of ammo. public void SetAmmo(ItemType item, ushort amount) => Inventory.ServerSetAmmo(item, amount); @@ -1279,8 +1566,11 @@ public List DropAllItems() public List DropAllAmmo() { List ammo = ListPool.Shared.Rent(); - foreach (KeyValuePair pair in Ammo) + + foreach (KeyValuePair pair in Ammo.ToDictionary(e => e.Key, e => e.Value)) + { ammo.AddRange(DropAmmo(pair.Key, pair.Value)); + } return ammo; } @@ -1296,7 +1586,9 @@ public List DropAllAmmo() public void ClearItems() { foreach (Item item in Items.ToArray()) + { RemoveItem(item); + } } /// @@ -1305,7 +1597,9 @@ public void ClearItems() public void ClearAmmo() { if (Ammo.Any(x => x.Value > 0)) + { Inventory.SendAmmoNextFrame = true; + } Ammo.Clear(); } @@ -1318,12 +1612,51 @@ public void ClearAmmo() public void ClearInventory(bool clearAmmo = true, bool clearItems = true) { if (clearAmmo) + { ClearAmmo(); + } if (clearItems) + { ClearItems(); + } + } + + /// + /// Gives a candy to the player. + /// + /// The candy to give the player. + /// The reason to grant the candy bag. + public void GiveCandy(CandyKindID candy, ItemAddReason reason) + => ReferenceHub.GrantCandy(candy, reason); + + /// + /// Gives a random candy to the player. + /// + /// The reason to grant the candy bag. + /// This will use , meaning it will use to choose the candy. + public void GiveRandomCandy(ItemAddReason reason = ItemAddReason.AdminCommand) + => GiveCandy(Scp330Candies.GetRandom(), reason); + + /// + /// Checks if a player has the specified . + /// + /// The permission to check the player for. + /// Whether the permission check was successful. + public bool HasPermission(PlayerPermissions permission) + { + PlayerPermissions currentPerms = (PlayerPermissions)ReferenceHub.serverRoles.Permissions; + return currentPerms.HasFlag(permission); } + /// + /// Adds regeneration to the player. + /// + /// The rate to heal per second. + /// How long the regeneration should last. + public void AddRegeneration(float rate, float duration) + => Scp330Bag.AddSimpleRegeneration(ReferenceHub, rate, duration); + /// /// Heals the player by the specified amount. /// @@ -1331,16 +1664,17 @@ public void ClearInventory(bool clearAmmo = true, bool clearItems = true) public void Heal(float amount) => ReferenceHub.playerStats.GetModule().ServerHeal(amount); /// - /// Creates and run a new AHP proccess. + /// Creates and run a new AHP process. /// /// Amount of AHP to be added. /// Adds limit to the AHP. /// Rate of AHP decay (per second). /// Value between 0 and 1. Defines what % of damage will be absorbed. /// Pauses decay for specified amount of seconds. - /// If true, it won't be automatically removed when reaches 0. + /// If true, it won't be automatically removed when reaches 0. /// Process in case it needs to be removed. Use to kill it. - public AhpProcess CreateAhpProcess(float amount, float limit, float decay, float efficacy, float sustain, bool persistant) => ReferenceHub.playerStats.GetModule().ServerAddProcess(amount, limit, decay, efficacy, sustain, persistant); + public AhpProcess CreateAhpProcess(float amount, float limit, float decay, float efficacy, float sustain, bool persistent) => + ReferenceHub.playerStats.GetModule().ServerAddProcess(amount, limit, decay, efficacy, sustain, persistent); /// /// Kills the AHP process. @@ -1356,6 +1690,13 @@ public void ClearInventory(bool clearAmmo = true, bool clearItems = true) /// The of role change. public void SetRole(RoleTypeId newRole, RoleChangeReason reason = RoleChangeReason.RemoteAdmin, RoleSpawnFlags flags = RoleSpawnFlags.All) => ReferenceHub.roleManager.ServerSetRole(newRole, reason, flags); + /// + /// Determines if is seen as spectator or their role based on visibility, permissions, and distance of this player. + /// + /// The other player to check. + /// The role this player sees for the other player. + public RoleTypeId GetRoleVisibilityFor(Player otherPlayer) => FpcServerPositionDistributor.GetVisibleRole(otherPlayer.ReferenceHub, ReferenceHub); + /// /// Disconnects the player from the server. /// @@ -1384,11 +1725,11 @@ public void SendHint(string text, HintEffect[] effects, float duration = 3f) => /// /// The text which will be displayed. /// The parameters to interpolate into the text. - /// The duration of which the text will be visible. /// The effects used for hint animations. See . + /// The duration of which the text will be visible. /// /// Parameters are interpolated into the string on the client. - /// E.g. "Test param1: {0} param2: {1}" + /// E.g. "Test param1: {0} param2: {1}". /// public void SendHint(string text, HintParameter[] parameters, HintEffect[]? effects = null, float duration = 3f) => ReferenceHub.hints.Show(new TextHint(text, parameters.IsEmpty() ? [new StringHintParameter(string.Empty)] : parameters, effects, duration)); @@ -1437,8 +1778,8 @@ public void DisableEffect() /// Enables a specific status effect. /// /// The type of the status effect to enable. - /// The duration of the status effect. /// The intensity of the status effect. + /// The duration of the status effect. /// Whether to add the duration to the current duration, if the effect is already active. /// A duration of 0 means that it will not expire. public void EnableEffect(byte intensity = 1, float duration = 0f, bool addDuration = false) @@ -1448,8 +1789,8 @@ public void EnableEffect(byte intensity = 1, float duration = 0f, bool addDur /// Enables a specific status effect. /// /// The status effect to enable. - /// The duration of the status effect. /// The intensity of the status effect. + /// The duration of the status effect. /// Whether to add the duration to the current duration, if the effect is already active. /// A duration of 0 means that it will not expire. public void EnableEffect(StatusEffectBase? effect, byte intensity = 1, float duration = 0f, bool addDuration = false) => effect?.ServerSetState(intensity, duration, addDuration); @@ -1459,7 +1800,7 @@ public void EnableEffect(byte intensity = 1, float duration = 0f, bool addDur /// /// The specified effect that will be looked for. /// The found player effect. - /// Whether the status effect was successfully retrieved. (And was cast successfully) + /// Whether the status effect was successfully retrieved (And was cast successfully). public bool TryGetEffect([NotNullWhen(true)] out T? effect) where T : StatusEffectBase => ReferenceHub.playerEffectsController.TryGetEffect(out effect) && effect != null; @@ -1502,8 +1843,8 @@ public void Reconnect(float delay = 3f, bool isFastRestart = false) => /// /// Kills the player. /// - /// The reason for the kill - /// The cassie announcement to make upon death. + /// The reason for the kill. + /// The CASSIE announcement to make upon death. /// Whether the player was successfully killed. public bool Kill(string reason, string cassieAnnouncement = "") => Damage(new CustomReasonDamageHandler(reason, StandardDamageHandler.KillValue, cassieAnnouncement)); @@ -1512,7 +1853,7 @@ public void Reconnect(float delay = 3f, bool isFastRestart = false) => /// /// The amount of damage. /// The reason of damage. - /// The cassie announcement send after death. + /// The CASSIE announcement send after death. /// Whether the player was successfully damaged. public bool Damage(float amount, string reason, string cassieAnnouncement = "") => Damage(new CustomReasonDamageHandler(reason, amount, cassieAnnouncement)); @@ -1520,7 +1861,7 @@ public void Reconnect(float delay = 3f, bool isFastRestart = false) => /// Damages player with explosion force. /// /// The amount of damage. - /// The player which attacked + /// The player which attacked. /// The force of explosion. /// The amount of armor penetration. /// Whether the player was successfully damaged. @@ -1583,31 +1924,6 @@ public TStore GetDataStore() /// public override string ToString() { - return $"[Player: DisplayName={DisplayName}, PlayerId={PlayerId}, NetworkId={NetworkId}, UserId={UserId}, IpAddress={IpAddress}, Role={Role}, IsServer={IsServer}, IsReady={IsReady}]"; - } - - /// - /// Handles the creation of a player in the server. - /// - /// The reference hub of the player. - private static void AddPlayer(ReferenceHub referenceHub) - { - if (!referenceHub.isLocalPlayer) - _ = new Player(referenceHub); - } - - /// - /// Handles the removal of a player from the server. - /// - /// The reference hub of the player. - private static void RemovePlayer(ReferenceHub referenceHub) - { - if (referenceHub.authManager.UserId != null) - UserIdCache.Remove(referenceHub.authManager.UserId); - - if (TryGet(referenceHub.gameObject, out Player? player)) - CustomDataStoreManager.RemovePlayer(player); - - Dictionary.Remove(referenceHub); + return $"[Player: DisplayName={DisplayName}, PlayerId={PlayerId}, NetworkId={NetworkId}, UserId={UserId}, IpAddress={IpAddress}, Role={Role}, IsHost={IsHost}, IsReady={IsReady}]"; } } diff --git a/LabApi/Features/Wrappers/Players/Ragdoll.cs b/LabApi/Features/Wrappers/Players/Ragdoll.cs index 3494bb97..2c7e5910 100644 --- a/LabApi/Features/Wrappers/Players/Ragdoll.cs +++ b/LabApi/Features/Wrappers/Players/Ragdoll.cs @@ -5,6 +5,8 @@ using PlayerRoles.PlayableScps.Scp049.Zombies; using PlayerRoles.Ragdolls; using PlayerStatsSystem; +using RelativePositioning; +using System; using System.Collections.Generic; using UnityEngine; @@ -25,6 +27,61 @@ public class Ragdoll ///
public static IReadOnlyCollection List => Dictionary.Values; + /// + /// Spawns a new ragdoll based on a specified player and damage handler. + /// + /// Player for ragdoll template. + /// Handler that is shown as a death cause. + /// New ragdoll. + public static Ragdoll? SpawnRagdoll(Player player, DamageHandlerBase handler) => SpawnRagdoll(player.Role, player.Position, player.Rotation, handler, player.DisplayName); + + /// + /// Attempts to spawn a ragdoll from specified role. Ragdoll is not created if specified role doesn't have any ragdoll model available. + /// + /// Target role type. + /// Spawn position. + /// Spawn rotation. + /// Damage handler of the death cause. + /// Nickname that is visible when hovering over. + /// Spawn scale. Converted to base ragdoll scale if . + /// Ragdoll object or . + public static Ragdoll? SpawnRagdoll(RoleTypeId role, Vector3 position, Quaternion rotation, DamageHandlerBase handler, string nickname, Vector3? scale = null) + { + BasicRagdoll ragdoll = RagdollManager.ServerCreateRagdoll(role, position, rotation, handler, nickname, scale); + return ragdoll == null ? null : Get(ragdoll); + } + + /// + /// Gets the ragdoll wrapper from the , or creates a new one if it doesn't exist. + /// + /// The ragdoll. + /// The requested ragdoll. + public static Ragdoll Get(BasicRagdoll ragdoll) => Dictionary.TryGetValue(ragdoll, out Ragdoll rag) ? rag : new Ragdoll(ragdoll); + + /// + /// Initializes the class to subscribe to events and handle the ragdoll caching. + /// + [InitializeWrapper] + internal static void Initialize() + { + Dictionary.Clear(); + + RagdollManager.OnRagdollSpawned += RagdollSpawned; + RagdollManager.OnRagdollRemoved += RagdollRemoved; + } + + /// + /// Event method for . + /// + /// New ragdoll. + private static void RagdollSpawned(BasicRagdoll ragdoll) => _ = new Ragdoll(ragdoll).Base; + + /// + /// Event method for . + /// + /// Destroyed ragdoll. + private static void RagdollRemoved(BasicRagdoll ragdoll) => Dictionary.Remove(ragdoll); + /// /// A private constructor to prevent external instantiation. /// @@ -32,7 +89,11 @@ public class Ragdoll private Ragdoll(BasicRagdoll ragdoll) { Base = ragdoll; - Dictionary.TryAdd(ragdoll, this); + + if (CanCache) + { + Dictionary.TryAdd(ragdoll, this); + } } /// @@ -40,6 +101,11 @@ private Ragdoll(BasicRagdoll ragdoll) /// public BasicRagdoll Base { get; private set; } + /// + /// Gets whether the base room instance was destroyed. + /// + public bool IsDestroyed => Base == null; + /// /// Gets or sets the role info of the ragdoll. /// This does NOT change the ragdoll visually. @@ -47,7 +113,15 @@ private Ragdoll(BasicRagdoll ragdoll) public RoleTypeId Role { get => Base.NetworkInfo.RoleType; - set => Base.NetworkInfo = new RagdollData(Base.NetworkInfo.OwnerHub, Base.NetworkInfo.Handler, value, Base.NetworkInfo.StartPosition, Base.NetworkInfo.StartRotation, Base.NetworkInfo.Nickname, Base.NetworkInfo.CreationTime); + set => Base.NetworkInfo = new RagdollData( + Base.Info.OwnerHub, + Base.Info.Handler, + value, + Base.Info.StartRelativePosition, + Base.Info.StartRelativeRotation, + Base.Info.Nickname, + Base.Info.CreationTime, + Base.Info.Serial); } /// @@ -56,17 +130,33 @@ public RoleTypeId Role public string Nickname { get => Base.NetworkInfo.Nickname; - set => Base.NetworkInfo = new RagdollData(Base.NetworkInfo.OwnerHub, Base.NetworkInfo.Handler, Base.NetworkInfo.RoleType, Base.NetworkInfo.StartPosition, Base.NetworkInfo.StartRotation, value, Base.NetworkInfo.CreationTime); + set => Base.NetworkInfo = new RagdollData( + Base.Info.OwnerHub, + Base.Info.Handler, + Base.Info.RoleType, + Base.Info.StartRelativePosition, + Base.Info.StartRelativeRotation, + value, + Base.Info.CreationTime, + Base.Info.Serial); } /// /// Gets or sets the ragdoll damage handler, providing death cause. /// - //TODO: Damage handler wrapper + // TODO: Damage handler wrapper public DamageHandlerBase DamageHandler { get => Base.NetworkInfo.Handler; - set => Base.NetworkInfo = new RagdollData(Base.NetworkInfo.OwnerHub, value, Base.NetworkInfo.RoleType, Base.NetworkInfo.StartPosition, Base.NetworkInfo.StartRotation, Base.NetworkInfo.Nickname, Base.NetworkInfo.CreationTime); + set => Base.NetworkInfo = new RagdollData( + Base.Info.OwnerHub, + value, + Base.Info.RoleType, + Base.Info.StartRelativePosition, + Base.Info.StartRelativeRotation, + Base.Info.Nickname, + Base.Info.CreationTime, + Base.Info.Serial); } /// @@ -78,7 +168,18 @@ public Vector3 Position set { Base.transform.position = value; - Base.NetworkInfo = new RagdollData(Base.NetworkInfo.OwnerHub, Base.NetworkInfo.Handler, Base.NetworkInfo.RoleType, value, Base.NetworkInfo.StartRotation, Base.NetworkInfo.Scale, Base.NetworkInfo.Nickname, Base.NetworkInfo.CreationTime); + RelativePosition relPos = new(value); + Quaternion relRot = WaypointBase.GetRelativeRotation(relPos.WaypointId, WaypointBase.GetWorldRotation(Base.Info.StartRelativePosition.WaypointId, Base.Info.StartRelativeRotation)); + Base.NetworkInfo = new RagdollData( + Base.Info.OwnerHub, + Base.Info.Handler, + Base.Info.RoleType, + relPos, + relRot, + Base.Info.Scale, + Base.Info.Nickname, + Base.Info.CreationTime, + Base.Info.Serial); } } @@ -91,13 +192,23 @@ public Quaternion Rotation set { Base.transform.rotation = value; - Base.NetworkInfo = new RagdollData(Base.NetworkInfo.OwnerHub, Base.NetworkInfo.Handler, Base.NetworkInfo.RoleType, Base.NetworkInfo.StartPosition, value, Base.NetworkInfo.Scale, Base.NetworkInfo.Nickname, Base.NetworkInfo.CreationTime); + Quaternion relRot = WaypointBase.GetRelativeRotation(Base.Info.StartRelativePosition.WaypointId, value); + Base.NetworkInfo = new RagdollData( + Base.Info.OwnerHub, + Base.Info.Handler, + Base.Info.RoleType, + Base.Info.StartRelativePosition, + relRot, + Base.Info.Scale, + Base.Info.Nickname, + Base.Info.CreationTime, + Base.Info.Serial); } } /// /// Gets or sets the ragdoll's scale. - /// Scale is set relative to the ragdoll's gameobject size. + /// Scale is set relative to the ragdoll's gameObject size. /// public Vector3 Scale { @@ -105,10 +216,24 @@ public Vector3 Scale set { Base.transform.localScale = value; - Base.NetworkInfo = new RagdollData(Base.NetworkInfo.OwnerHub, Base.NetworkInfo.Handler, Base.NetworkInfo.RoleType, Base.NetworkInfo.StartPosition, Base.NetworkInfo.StartRotation, Vector3.Scale(value, RagdollManager.GetDefaultScale(Role)), Base.NetworkInfo.Nickname, Base.NetworkInfo.CreationTime); + Base.NetworkInfo = new RagdollData( + Base.Info.OwnerHub, + Base.Info.Handler, + Base.Info.RoleType, + Base.Info.StartRelativePosition, + Base.Info.StartRelativeRotation, + Vector3.Scale(value, RagdollManager.GetDefaultScale(Role)), + Base.Info.Nickname, + Base.Info.CreationTime, + Base.Info.Serial); } } + /// + /// Gets the serial number of the ragdoll. + /// + public ushort Serial => Base.NetworkInfo.Serial; + /// /// Gets or sets whether the corpse is consumed. /// @@ -127,18 +252,27 @@ public bool IsConsumed } } + /// + /// Whether to cache this wrapper. + /// + protected bool CanCache => !IsDestroyed && Base.isActiveAndEnabled; + /// /// Gets whether the ragdoll is revivable by SCP-049 player. /// - /// Player who is SCP-049 + /// Player who is SCP-049. /// True if corpse is revivable. False if it isn't or specified player is not SCP-049. public bool IsRevivableBy(Player scp049) { if (scp049.RoleBase is not Scp049Role role) + { return false; + } if (!role.SubroutineModule.TryGetSubroutine(out Scp049ResurrectAbility ability)) + { return false; + } return ability.CheckRagdoll(Base); } @@ -171,7 +305,7 @@ public void UnFreeze() Destroy(); Dictionary.Remove(Base); - Base = RagdollManager.ServerCreateRagdoll(data.RoleType, data.StartPosition, data.StartRotation, data.Handler, data.Nickname, data.Scale, data.Serial); + Base = RagdollManager.ServerCreateRagdoll(data.RoleType, data.StartRelativePosition.Position, data.StartRelativeRotation, data.Handler, data.Nickname, data.Scale, data.Serial); Dictionary.TryAdd(Base, this); RagdollManager.OnRagdollSpawned += RagdollSpawned; @@ -183,60 +317,4 @@ public override string ToString() { return $"[Ragdoll: Nickname={Nickname}, Role={Role}, DamageHandler={DamageHandler}, Position={Position}, Rotation={Rotation}, Scale={Scale}, IsConsumed={IsConsumed}]"; } - - /// - /// Spawns a new ragdoll based on a specified player and damage handler. - /// - /// Player for ragdoll template. - /// Handler that is shown as a death cause. - /// New ragdoll. - public static Ragdoll? SpawnRagdoll(Player player, DamageHandlerBase handler) => SpawnRagdoll(player.Role, player.Position, player.Rotation, handler, player.DisplayName); - - /// - /// Attempts to spawn a ragdoll from specified role. Ragdoll is not created if specified role doesn't have any ragdoll model available. - /// - /// Target role type. - /// Spawn position. - /// Spawn rotation. - /// Spawn scale. Converted to base ragdoll scale if . - /// Damage handler of the death cause. - /// Nickname that is visible when hovering over. - /// Ragdoll object or . - public static Ragdoll? SpawnRagdoll(RoleTypeId role, Vector3 position, Quaternion rotation, DamageHandlerBase handler, string nickname, Vector3? scale = null) - { - BasicRagdoll ragdoll = RagdollManager.ServerCreateRagdoll(role, position, rotation, handler, nickname, scale); - return ragdoll == null ? null : Get(ragdoll); - } - - /// - /// Initializes the class to subscribe to events and handle the ragdoll caching. - /// - [InitializeWrapper] - internal static void Initialize() - { - Dictionary.Clear(); - - RagdollManager.OnRagdollSpawned += RagdollSpawned; - RagdollManager.OnRagdollRemoved += RagdollRemoved; - } - - /// - /// Event method for . - /// - /// New ragdoll. - private static void RagdollSpawned(BasicRagdoll ragdoll) => _ = new Ragdoll(ragdoll).Base; - - /// - /// Event method for . - /// - /// Destroyed ragdoll. - private static void RagdollRemoved(BasicRagdoll ragdoll) => Dictionary.Remove(ragdoll); - - /// - /// Gets the ragdoll wrapper from the , or creates a new one if it doesn't exist. - /// - /// The ragdoll. - /// The requested ragdoll. - public static Ragdoll Get(BasicRagdoll ragdoll) => Dictionary.TryGetValue(ragdoll, out Ragdoll rag) ? rag : new Ragdoll(ragdoll); - } \ No newline at end of file diff --git a/LabApi/Features/Wrappers/Server/ReservedSlots.cs b/LabApi/Features/Wrappers/Server/ReservedSlots.cs index 750a9393..fc5ef40e 100644 --- a/LabApi/Features/Wrappers/Server/ReservedSlots.cs +++ b/LabApi/Features/Wrappers/Server/ReservedSlots.cs @@ -39,11 +39,13 @@ public static class ReservedSlots /// /// Gives the player a reserved slot and saves it to file. /// - /// The userid. + /// The user id. public static void Add(string userId) { if (HasReservedSlot(userId)) + { return; + } List lines = FileManager.ReadAllLinesList(FilePath); lines.Add(userId); @@ -65,7 +67,9 @@ public static void Add(string userId) public static bool Remove(string userId) { if (!HasReservedSlot(userId)) + { return false; + } List lines = FileManager.ReadAllLinesList(FilePath); @@ -84,4 +88,3 @@ public static bool Remove(string userId) /// Whether the player was found and removed from the reserved slots. public static bool Remove(Player player) => Remove(player.UserId); } - diff --git a/LabApi/Features/Wrappers/Players/Server.cs b/LabApi/Features/Wrappers/Server/Server.cs similarity index 80% rename from LabApi/Features/Wrappers/Players/Server.cs rename to LabApi/Features/Wrappers/Server/Server.cs index 48fd949c..f24e69ea 100644 --- a/LabApi/Features/Wrappers/Players/Server.cs +++ b/LabApi/Features/Wrappers/Server/Server.cs @@ -1,6 +1,6 @@ -using CommandSystem; +using Achievements; +using CommandSystem; using CustomPlayerEffects; -using Generators; using InventorySystem.Configs; using LabApi.Features.Permissions; using LabApi.Features.Permissions.Providers; @@ -10,6 +10,8 @@ using RoundRestarting; using System; using System.Collections.Generic; +using System.Linq; +using System.Text; using UnityEngine; using static BanHandler; @@ -20,20 +22,10 @@ namespace LabApi.Features.Wrappers; /// public static class Server { - /// - /// Initializes the class to subscribe to events. - /// - [InitializeWrapper] - internal static void Initialize() - { - ReferenceHub.OnPlayerAdded += AddHost; - ReferenceHub.OnPlayerRemoved += RemoveHost; - } - /// /// The Instance. /// - public static Player? Host { get; private set; } + public static Player? Host { get; internal set; } /// /// Gets the IP address of the server. @@ -128,7 +120,9 @@ public static bool FriendlyFire set { if (FriendlyFire == value) + { return; + } ServerConsole.FriendlyFire = value; ServerConfigSynchronizer.Singleton.RefreshMainBools(); @@ -136,6 +130,25 @@ public static bool FriendlyFire } } + /// + /// Gets or sets a value indicating whether achievement granting is enabled. + /// + public static bool AchievementsEnabled + { + get => !AchievementManager.AchievementsDisabled; + set + { + if (AchievementManager.AchievementsDisabled != value) + { + return; + } + + AchievementManager.AchievementsDisabled = !value; + ServerConfigSynchronizer.Singleton.RefreshMainBools(); + ServerConfigSynchronizer.OnRefreshed?.Invoke(); + } + } + /// /// Gets or sets the server name as seen on the server list. /// @@ -148,7 +161,7 @@ public static string ServerListName /// /// Gets or sets the server name as seen on the player list. /// - // TODO: maybe move to a playerlist wrapper? + // TODO: maybe move to a player list wrapper? public static string PlayerListName { get => PlayerList.Title.Value; @@ -158,13 +171,21 @@ public static string PlayerListName /// /// Gets or sets the refresh rate for the player list name. /// - // TODO: maybe move to a playerlist wrapper? + // TODO: maybe move to a player list wrapper? public static float PlayerListNameRefreshRate { get => PlayerList.RefreshRate.Value; set => PlayerList.RefreshRate.Value = value; } + /// + /// Gets or sets whether the server has been marked as transparently modded.
+ /// For this status to be applied automatically, all installed plugins must have their + /// property set to .
+ /// For more information, see article 5.2 in the official documentation: https://scpslgame.com/csg. + ///
+ public static bool IsTransparentlyModded { get; internal set; } + /// /// Gets the Category limits. /// @@ -188,7 +209,7 @@ public static float PlayerListNameRefreshRate /// /// Gets the instance. /// - public static GameConsoleCommandHandler GameConsoleCommandHandler => GameCore.Console.singleton.ConsoleCommandHandler; + public static GameConsoleCommandHandler GameConsoleCommandHandler => GameCore.Console.ConsoleCommandHandler; /// /// Gets the of the server. @@ -260,17 +281,21 @@ public static bool BanUserId(string userId, string reason, long duration, string public static bool BanUserId(string userId, Player? issuer, string reason, long duration, string bannedPlayerNickname = "UnknownName") { if (string.IsNullOrEmpty(userId) || string.IsNullOrEmpty(reason) || issuer == null) + { return false; + } - return IssueBan(new BanDetails() - { - Id = userId, - IssuanceTime = TimeBehaviour.CurrentTimestamp(), - Expires = TimeBehaviour.GetBanExpirationTime((uint)duration), - Issuer = issuer.LogName, - OriginalName = bannedPlayerNickname, - Reason = reason, - }, BanType.UserId); + return IssueBan( + new BanDetails() + { + Id = userId, + IssuanceTime = TimeBehaviour.CurrentTimestamp(), + Expires = TimeBehaviour.GetBanExpirationTime((uint)duration), + Issuer = issuer.LogName, + OriginalName = bannedPlayerNickname, + Reason = reason, + }, + BanType.UserId); } /// @@ -296,17 +321,21 @@ public static bool BanIpAddress(string ipAddress, string reason, long duration, public static bool BanIpAddress(string ipAddress, Player? issuer, string reason, long duration, string bannedPlayerNickname = "UnknownName") { if (string.IsNullOrEmpty(ipAddress) || string.IsNullOrEmpty(reason) || issuer == null) + { return false; + } - return IssueBan(new BanDetails() - { - Id = ipAddress, - IssuanceTime = TimeBehaviour.CurrentTimestamp(), - Expires = TimeBehaviour.GetBanExpirationTime((uint)duration), - Issuer = issuer.LogName, - OriginalName = bannedPlayerNickname, - Reason = reason, - }, BanType.IP); + return IssueBan( + new BanDetails() + { + Id = ipAddress, + IssuanceTime = TimeBehaviour.CurrentTimestamp(), + Expires = TimeBehaviour.GetBanExpirationTime((uint)duration), + Issuer = issuer.LogName, + OriginalName = bannedPlayerNickname, + Reason = reason, + }, + BanType.IP); } /// @@ -317,7 +346,9 @@ public static bool BanIpAddress(string ipAddress, Player? issuer, string reason, public static bool UnbanUserId(string userId) { if (string.IsNullOrEmpty(userId) || !IsPlayerBanned(userId)) + { return false; + } RemoveBan(userId, BanType.UserId); return true; @@ -331,7 +362,9 @@ public static bool UnbanUserId(string userId) public static bool UnbanIpAddress(string ipAddress) { if (string.IsNullOrEmpty(ipAddress) || !IsPlayerBanned(ipAddress)) + { return false; + } RemoveBan(ipAddress, BanType.IP); return true; @@ -345,7 +378,9 @@ public static bool UnbanIpAddress(string ipAddress) public static bool IsPlayerBanned(string value) { if (string.IsNullOrEmpty(value)) + { return false; + } return (value.Contains("@") ? GetBan(value, BanType.UserId) : GetBan(value, BanType.IP)) != null; } @@ -353,7 +388,7 @@ public static bool IsPlayerBanned(string value) /// /// Gets all banned players. /// - /// List of all banned players. + /// A pooled list of all banned players. public static List GetAllBannedPlayers() { List bans = ListPool.Shared.Rent(); @@ -366,7 +401,7 @@ public static List GetAllBannedPlayers() /// Gets all banned players by ban type. /// /// The type of ban. - /// List of specified ban types. + /// A pooled list of specified ban types. public static List GetAllBannedPlayers(BanType banType) => GetBans(banType); #endregion @@ -379,6 +414,7 @@ public static List GetAllBannedPlayers() /// /// Restarts the server and reconnects all players to target server port. /// + /// The port number of the server to send all the players too. public static void Restart(ushort redirectPort) { NetworkServer.SendToAll(new RoundRestartMessage(RoundRestartType.RedirectRestart, 0.1f, redirectPort, true, false)); @@ -393,6 +429,7 @@ public static void Restart(ushort redirectPort) /// /// Shutdowns the server and reconnects all players to target server port. /// + /// The port number of the server to send all the players too. public static void Shutdown(ushort redirectPort) { NetworkServer.SendToAll(new RoundRestartMessage(RoundRestartType.RedirectRestart, 0.1f, redirectPort, true, false)); @@ -404,6 +441,7 @@ public static void Shutdown(ushort redirectPort) /// /// The command name. /// The running the command. + /// The commands response. public static string RunCommand(string command, CommandSender? sender = null) => ServerConsole.EnterCommand(command, sender); @@ -417,7 +455,9 @@ public static string RunCommand(string command, CommandSender? sender = null) => public static void SendBroadcast(string message, ushort duration, Broadcast.BroadcastFlags type = Broadcast.BroadcastFlags.Normal, bool shouldClearPrevious = false) { if (shouldClearPrevious) + { ClearBroadcasts(); + } Broadcast.Singleton.RpcAddElement(message, duration, type); } @@ -433,41 +473,62 @@ public static void SendBroadcast(string message, ushort duration, Broadcast.Broa public static void SendBroadcast(Player player, string message, ushort duration, Broadcast.BroadcastFlags type = Broadcast.BroadcastFlags.Normal, bool shouldClearPrevious = false) { if (shouldClearPrevious) + { ClearBroadcasts(player); + } Broadcast.Singleton.TargetAddElement(player.Connection, message, duration, type); } /// - /// Clears broadcast's for all players. + /// Sends the admin chat messages to all players with permissions. /// - public static void ClearBroadcasts() => Broadcast.Singleton.RpcClearElements(); + /// The message to send. + /// Whether the message should not appear in broadcast. + public static void SendAdminChatMessage(string message, bool isSilent = false) => SendAdminChatMessage(Player.ReadyList.Where(static n => n.UserGroup != null && PermissionsHandler.IsPermitted(n.UserGroup.Permissions, PlayerPermissions.AdminChat)), message, isSilent); /// - /// Clears broadcast's for the specified . + /// Sends admin chat message to all specified players. /// - /// The player to clear the broadcast's. - public static void ClearBroadcasts(Player player) => Broadcast.Singleton.TargetClearElements(player.Connection); + /// The target players. + /// The message to send. + /// Whether the message should not appear in broadcast. + public static void SendAdminChatMessage(IEnumerable targetPlayers, string message, bool isSilent = false) + { + StringBuilder sb = StringBuilderPool.Shared.Rent(); + + sb.Append(Host!.NetworkId); + sb.Append('!'); + + if (isSilent) + { + sb.Append("@@"); + } + + sb.Append(message); + + string toSend = StringBuilderPool.Shared.ToStringReturn(sb); + foreach (Player player in targetPlayers) + { + if (!player.IsPlayer || !player.IsReady) + { + continue; + } + + player.ReferenceHub.encryptedChannelManager.TrySendMessageToClient(toSend, EncryptedChannelManager.EncryptedChannel.AdminChat); + } + } /// - /// Handles the creation of the host in the server. + /// Clears broadcast's for all players. /// - /// The reference hub to add. - private static void AddHost(ReferenceHub referenceHub) - { - if (referenceHub.isLocalPlayer) - Host = new Player(referenceHub); - } + public static void ClearBroadcasts() => Broadcast.Singleton.RpcClearElements(); /// - /// Handles the removal of the host from the server. + /// Clears broadcast's for the specified . /// - /// The reference hub to remove. - private static void RemoveHost(ReferenceHub referenceHub) - { - if (referenceHub.isLocalPlayer) - Host = null; - } + /// The player to clear the broadcast's. + public static void ClearBroadcasts(Player player) => Broadcast.Singleton.TargetClearElements(player.Connection); /// /// Interface for getting and setting key value limits. @@ -490,7 +551,7 @@ TValue this[TKey index] } /// - /// Private implementation class for synchronizing ItemCategory limits + /// Private implementation class for synchronizing ItemCategory limits. /// private class CategoryLimitsSynchronizer : ILimit { @@ -501,7 +562,9 @@ public sbyte this[ItemCategory category] set { if (!InventoryLimits.StandardCategoryLimits.ContainsKey(category)) + { throw new IndexOutOfRangeException($"Index {category} was not a valid ItemCategory type"); + } InventoryLimits.StandardCategoryLimits[category] = value; ServerConfigSynchronizer.Singleton.RefreshCategoryLimits(); @@ -521,7 +584,9 @@ public ushort this[ItemType ammo] set { if (!InventoryLimits.StandardAmmoLimits.ContainsKey(ammo)) + { throw new IndexOutOfRangeException($"Index {ammo} was not a valid Ammo type"); + } InventoryLimits.StandardAmmoLimits[ammo] = value; ServerConfigSynchronizer.Singleton.RefreshAmmoLimits(); @@ -529,4 +594,3 @@ public ushort this[ItemType ammo] } } } - diff --git a/LabApi/Features/Wrappers/Server/Whitelist.cs b/LabApi/Features/Wrappers/Server/Whitelist.cs index e85bbe17..fcd5078d 100644 --- a/LabApi/Features/Wrappers/Server/Whitelist.cs +++ b/LabApi/Features/Wrappers/Server/Whitelist.cs @@ -41,7 +41,7 @@ public static bool WhitelistEnabled public static bool IsOnWhitelist(string userId) => WhiteList.IsOnWhitelist(userId); /// - /// Chhecks if the player is allowed on the server if the whitelist is enabled. + /// Checks if the player is allowed on the server if the whitelist is enabled. /// /// The user id of the player. /// Whether the player is whitelisted. Will always return true if whitelist is disabled. @@ -55,11 +55,13 @@ public static bool WhitelistEnabled /// /// Adds player to whitelist and saves it to file. /// - /// The userid. + /// The user id. public static void Add(string userId) { if (IsOnWhitelist(userId)) + { return; + } List lines = FileManager.ReadAllLinesList(FilePath); lines.Add(userId); @@ -81,7 +83,9 @@ public static void Add(string userId) public static bool Remove(string userId) { if (!IsOnWhitelist(userId)) + { return false; + } List lines = FileManager.ReadAllLinesList(FilePath); diff --git a/LabApi/LabApi.csproj b/LabApi/LabApi.csproj index 0a4ab084..d25a73be 100644 --- a/LabApi/LabApi.csproj +++ b/LabApi/LabApi.csproj @@ -6,7 +6,7 @@ x64 12.0 - 1.1.0 + 1.1.5 LabApi Northwood.LabAPI @@ -17,7 +17,7 @@ https://www.nuget.org/packages/Northwood.LabAPI/ https://github.com/northwood-studios/LabAPI/ git - © 2025 Northwood Studios + © 2026 Northwood Studios enable AnyCPU @@ -29,9 +29,20 @@ LICENSE true + + $(SolutionDir)StyleCopAnalyzers.ruleset + + + + + + + all + runtime; build; native; contentfiles; analyzers; buildtransitive + @@ -63,7 +74,7 @@ - + diff --git a/LabApi/Loader/CommandLoader.cs b/LabApi/Loader/CommandLoader.cs index e9bbe8b4..57fc35fb 100644 --- a/LabApi/Loader/CommandLoader.cs +++ b/LabApi/Loader/CommandLoader.cs @@ -22,16 +22,16 @@ public static class CommandLoader /// /// The dictionary of command handlers. /// - public static Dictionary CommandHandlers { get; } = new() + public static Dictionary> CommandHandlers { get; } = new() { // The server console command handler. - [typeof(GameConsoleCommandHandler)] = GameCore.Console.singleton.ConsoleCommandHandler, + [typeof(GameConsoleCommandHandler)] = [GameCore.Console.ConsoleCommandHandler], // The remote admin command handler. - [typeof(RemoteAdminCommandHandler)] = CommandProcessor.RemoteAdminCommandHandler, + [typeof(RemoteAdminCommandHandler)] = [CommandProcessor.RemoteAdminCommandHandler], // The client console command handler. - [typeof(ClientCommandHandler)] = QueryProcessor.DotCommandHandler + [typeof(ClientCommandHandler)] = [QueryProcessor.DotCommandHandler], }; /// @@ -44,16 +44,6 @@ public static class CommandLoader /// public static IEnumerable? LabApiCommands { get; private set; } - /// - /// Registers all commands in the LabAPI solution. - /// - internal static void RegisterCommands() - { - // We register all commands in the LabAPI assembly. - // We convert it to an array since IEnumerable are lazy and need to be iterated through to be executed. - LabApiCommands = RegisterCommands(Assembly.GetExecutingAssembly(), "LabApi").ToArray(); - } - /// /// Registers all commands in the given . /// @@ -80,6 +70,7 @@ public static void RegisterCommands(this Plugin plugin) /// /// The to register the commands from. /// The name of the plugin to log to use when logging errors. + /// An enumeration of all registered commands. public static IEnumerable RegisterCommands(Assembly assembly, string logName = "") { // We use reflection to get all types in the assembly. @@ -107,14 +98,18 @@ public static IEnumerable RegisterCommands(Type type, string logName = { // We check if the type implements the ICommand interface. if (!typeof(ICommand).IsAssignableFrom(type)) + { yield break; + } // We iterate through all custom attributes of the type. foreach (CustomAttributeData attributeData in type.GetCustomAttributesData()) { // If the attribute type is not a CommandHandlerAttribute, we continue. if (attributeData.AttributeType != typeof(CommandHandlerAttribute)) + { continue; + } // We retrieve the command handler type from the attribute data. Type commandHandlerType = (Type)attributeData.ConstructorArguments[0].Value; @@ -132,7 +127,9 @@ public static IEnumerable RegisterCommands(Type type, string logName = // And we finally register the command. if (!TryRegisterCommand(type, commandHandlerType, out ICommand? command, logName)) + { continue; + } // We add the command to the list of registered commands. yield return command; @@ -144,20 +141,15 @@ public static IEnumerable RegisterCommands(Type type, string logName = /// /// The of the command to register. /// The of the command handler to register the command to. - /// The name of the plugin to log to use when logging errors. /// The registered command if the command was successfully registered. + /// The name of the plugin to log to use when logging errors. + /// Whether the command registered successfully. public static bool TryRegisterCommand(Type commandType, Type commandHandlerType, [NotNullWhen(true)] out ICommand? command, string logName) { command = null; - if (CommandHandlers.ContainsKey(commandType)) - { - // This parent command was already registered. - return false; - } - // We try to get the command handler from the dictionary of command handlers. - if (!CommandHandlers.TryGetValue(commandHandlerType, out CommandHandler commandHandler)) + if (!CommandHandlers.TryGetValue(commandHandlerType, out List commandHandlers)) { Logger.Error($"{LoggerPrefix} Unable to register command '{commandType.Name}' from '{logName}'. CommandHandler '{commandHandlerType}' not found."); return false; @@ -182,8 +174,17 @@ public static bool TryRegisterCommand(Type commandType, Type commandHandlerType, throw; } - // We finally try to register the command in the command handler. - return TryRegisterCommand(command, commandHandler, logName); + // We iterate through all command handlers (including subcommand that has multiple handler). + foreach (CommandHandler commandHandler in commandHandlers) + { + // We finally try to register the command in the command handler. + if (!TryRegisterCommand(command, commandHandler, logName)) + { + return false; + } + } + + return true; } /// @@ -197,22 +198,35 @@ public static bool TryRegisterCommand(ICommand command, CommandHandler commandHa { try { + // We check if the command already registered (might happen) and just return. + if (commandHandler.AllCommands.Any(x => string.Equals(x.Command, command.Command, StringComparison.OrdinalIgnoreCase))) + { + return true; + } + // We try to register the command. commandHandler.RegisterCommand(command); // We check if the command type is a parent command. if (command is not ParentCommand parentCommand) + { return true; + } // If the command type is a parent command, we register the command type as a command handler type. // This allows us to register subcommands to the parent command by just using the CommandHandlerAttribute. // [CommandHandler(typeof(MyParentCommand))] - Type commandType = command.GetType(); + if (!CommandHandlers.ContainsKey(commandType)) { // We add the command type to the dictionary of command handlers. - CommandHandlers.Add(commandType, parentCommand); + CommandHandlers[commandType] = []; + } + + if (!CommandHandlers[commandType].Contains(parentCommand)) + { + CommandHandlers[commandType].Add(parentCommand); } // We can finally return true. @@ -241,7 +255,9 @@ public static bool TryRegisterCommand(ICommand command, CommandHandler commandHa public static void UnregisterCommands(this Plugin plugin) { if (!RegisteredCommands.TryGetValue(plugin, out IEnumerable commands)) + { return; + } // We iterate through all commands in the plugin. foreach (ICommand command in commands) @@ -261,22 +277,39 @@ public static void UnregisterCommands(this Plugin plugin) public static void UnregisterCommand(ICommand command) { // We iterate through all command handlers. - foreach (CommandHandler commandHandler in CommandHandlers.Values) + foreach (List commandHandlers in CommandHandlers.Values) { - // If the command handler does not contain the command, we continue. - if (!commandHandler.AllCommands.Contains(command)) - continue; + foreach (CommandHandler commandHandler in commandHandlers) + { + // If the command handler does not contain the command, we continue. + if (!commandHandler.AllCommands.Contains(command)) + { + continue; + } - // We manually unregister the command from the command handler. - commandHandler.UnregisterCommand(command); + // We manually unregister the command from the command handler. + commandHandler.UnregisterCommand(command); + } } // We check if the command is a parent command. if (command is not ParentCommand parentCommand) + { return; + } // If the command is a parent command, we remove the command type from the dictionary of command handlers. Type commandType = parentCommand.GetType(); CommandHandlers.Remove(commandType); } + + /// + /// Registers all commands in the LabAPI solution. + /// + internal static void RegisterCommands() + { + // We register all commands in the LabAPI assembly. + // We convert it to an array since IEnumerable are lazy and need to be iterated through to be executed. + LabApiCommands = RegisterCommands(Assembly.GetExecutingAssembly(), "LabApi").ToArray(); + } } \ No newline at end of file diff --git a/LabApi/Loader/ConfigurationLoader.cs b/LabApi/Loader/ConfigurationLoader.cs index 59402ff7..b91899d0 100644 --- a/LabApi/Loader/ConfigurationLoader.cs +++ b/LabApi/Loader/ConfigurationLoader.cs @@ -1,4 +1,5 @@ using LabApi.Features.Console; +using LabApi.Features.Wrappers; using LabApi.Loader.Features.Paths; using LabApi.Loader.Features.Plugins; using LabApi.Loader.Features.Plugins.Configuration; @@ -6,7 +7,6 @@ using System; using System.Diagnostics.CodeAnalysis; using System.IO; -using LabApi.Features.Wrappers; namespace LabApi.Loader; @@ -75,7 +75,9 @@ public static bool TryReadConfig(this Plugin plugin, string fileName, [ // If the configuration file doesn't exist, we return false to indicate that the configuration wasn't successfully read. if (!File.Exists(path)) + { return false; + } // We read the configuration file. string serializedConfig = File.ReadAllText(path); @@ -105,8 +107,6 @@ public static bool TryReadConfig(this Plugin plugin, string fileName, [ public static bool TryLoadConfig(this Plugin plugin, string fileName, [NotNullWhen(true)] out TConfig? config, bool isGlobal = false) where TConfig : class, new() { - config = null; - // We retrieve the path of the configuration file. string path = plugin.GetConfigPath(fileName, isGlobal); @@ -120,10 +120,11 @@ public static bool TryLoadConfig(this Plugin plugin, string fileName, [ return plugin.TrySaveConfig(config, fileName, isGlobal); } } + // We try to read the configuration from its file. else if (plugin.TryReadConfig(fileName, out config, isGlobal)) { - // We save the configuration to update new properties and return whether it was successfully saved. + // We save the configuration to update new properties and return whether it was successfully saved. return plugin.TrySaveConfig(config, fileName, isGlobal); } @@ -194,6 +195,9 @@ public static bool TryCreateDefaultConfig(this Plugin plugin, [NotNullW /// /// Gets the configuration directory for a plugin, considering whether it's global or per-port. /// + /// The plugin to gets its config directory. + /// Whether the directory is for global configs or per-port ones. + /// The of the plugin. public static DirectoryInfo GetConfigDirectory(this Plugin plugin, bool isGlobal = false) { DirectoryInfo baseDir = PathManager.Configs; @@ -215,7 +219,9 @@ public static string GetConfigPath(this Plugin plugin, string fileName, bool isG // We check if the file name doesn't end with .yml or .yaml and add it if it doesn't. if (!fileName.EndsWith(".yml", StringComparison.InvariantCultureIgnoreCase) && !fileName.EndsWith(".yaml", StringComparison.InvariantCultureIgnoreCase)) + { fileName += ".yml"; + } // We return the path of the configuration file. return Path.Combine(directory.FullName, fileName); @@ -230,7 +236,9 @@ public static bool TryLoadProperties(this Plugin plugin) { // We try to load the properties of the plugin and return them. if (!plugin.TryLoadConfig(PropertiesFileName, out Properties? properties)) + { return false; + } // We set the properties of the plugin. plugin.Properties = properties; diff --git a/LabApi/Loader/Features/Commands/Extensions/CommandExtensions.cs b/LabApi/Loader/Features/Commands/Extensions/CommandExtensions.cs new file mode 100644 index 00000000..f6de6789 --- /dev/null +++ b/LabApi/Loader/Features/Commands/Extensions/CommandExtensions.cs @@ -0,0 +1,38 @@ +using CommandSystem; +using NorthwoodLib.Pools; +using System; +using System.Text; + +namespace LabApi.Loader.Features.Commands.Extensions; + +/// +/// Extension class for LabAPI commands. +/// +public static class CommandExtensions +{ + /// + /// Responds to a parent command execution by listing out all sub commands, and/or printing an invalid arg message if any invalid args were provided. + /// + /// The parent command instance. + /// The arguments passed to the parent command. + /// The output response. + /// if there were no arguments, otherwise . + public static bool ListSubCommands(ParentCommand parent, ArraySegment arguments, out string response) + { + StringBuilder sb = StringBuilderPool.Shared.Rent(); + + sb.AppendLine(arguments.Count > 0 + ? $"'{arguments.At(0)}' was not a valid sub command." + : "You must specify a subcommand when executing this command."); + + sb.AppendLine("Valid subcommands:"); + + foreach (ICommand subCommand in parent.AllCommands) + { + sb.AppendLine($" {subCommand.Command} - {subCommand.Description} Aliases [{string.Join(" ", subCommand.Aliases)}]"); + } + + response = StringBuilderPool.Shared.ToStringReturn(sb); + return arguments.Count == 0; + } +} diff --git a/LabApi/Loader/Features/Commands/LabApiParentCommand.cs b/LabApi/Loader/Features/Commands/LabApiParentCommand.cs new file mode 100644 index 00000000..53e306b9 --- /dev/null +++ b/LabApi/Loader/Features/Commands/LabApiParentCommand.cs @@ -0,0 +1,31 @@ +using CommandSystem; +using System; +using static LabApi.Loader.Features.Commands.Extensions.CommandExtensions; + +namespace LabApi.Loader.Features.Commands; + +/// +/// LabAPI parent command used for all LabAPI related subcommands. +/// +[CommandHandler(typeof(RemoteAdminCommandHandler))] +[CommandHandler(typeof(GameConsoleCommandHandler))] +public class LabApiParentCommand : ParentCommand +{ + /// + public override string Command => "labapi"; + + /// + public override string[] Aliases => ["lab"]; + + /// + public override string Description => "Parent command for all LabAPI subcommands."; + + /// + public override void LoadGeneratedCommands() + { + } + + /// + protected override bool ExecuteParent(ArraySegment arguments, ICommandSender sender, out string response) + => ListSubCommands(this, arguments, out response); +} diff --git a/LabApi/Features/Permissions/Commands/PluginPermissionsCommand.cs b/LabApi/Loader/Features/Commands/PluginPermissionsCommand.cs similarity index 64% rename from LabApi/Features/Permissions/Commands/PluginPermissionsCommand.cs rename to LabApi/Loader/Features/Commands/PluginPermissionsCommand.cs index a38e4747..9d0f92bd 100644 --- a/LabApi/Features/Permissions/Commands/PluginPermissionsCommand.cs +++ b/LabApi/Loader/Features/Commands/PluginPermissionsCommand.cs @@ -1,29 +1,30 @@ +using CommandSystem; +using LabApi.Features.Permissions; using System; using System.Diagnostics.CodeAnalysis; using System.Linq; -using CommandSystem; -namespace LabApi.Features.Permissions.Commands; +namespace LabApi.Loader.Features.Commands; /// /// Represents a command that allows players to view their plugin permissions. /// -[CommandHandler(typeof(RemoteAdminCommandHandler))] +[CommandHandler(typeof(LabApiParentCommand))] public class PluginPermissionsCommand : ICommand { /// - public string Command { get; } = "pluginpermissions"; + public string Command { get; } = "permissions"; /// - public string[] Aliases { get; } = ["pp", "pluginperms"]; + public string[] Aliases { get; } = ["p", "perms"]; /// - public string Description { get; } = "Views your plugin permissions."; + public string Description { get; } = "Shows your LabAPI plugin permissions."; /// public bool Execute(ArraySegment arguments, ICommandSender sender, [UnscopedRef] out string response) { - response = "You have the following plugin permissions:\n"; + response = "You have the following LabAPI plugin permissions:\n"; foreach ((Type provider, string[] perms) in sender.GetPermissionsByProvider()) { @@ -35,7 +36,7 @@ public bool Execute(ArraySegment arguments, ICommandSender sender, [Unsc continue; } - response = perms.Aggregate(response, (current, perm) => current + $"+ {perm}\n"); + response = perms.Aggregate(response, static (current, perm) => current + $"+ {perm}\n"); } return true; diff --git a/LabApi/Loader/Features/Commands/Reload/ConfigsCommand.cs b/LabApi/Loader/Features/Commands/Reload/ConfigsCommand.cs new file mode 100644 index 00000000..5ec85e51 --- /dev/null +++ b/LabApi/Loader/Features/Commands/Reload/ConfigsCommand.cs @@ -0,0 +1,64 @@ +using CommandSystem; +using LabApi.Loader.Features.Plugins; +using NorthwoodLib.Pools; +using System; +using System.Text; + +namespace LabApi.Loader.Features.Commands.Reload; + +/// +/// Represents a command used to reload all plugin configs. +/// +[CommandHandler(typeof(ReloadParentCommand))] +public class ConfigsCommand : ICommand +{ + /// + public string Command => "configs"; + + /// + public string[] Aliases => ["c", "cfg"]; + + /// + public string Description => "Reloads configs for all LabAPI plugins."; + + /// + public bool Execute(ArraySegment arguments, ICommandSender sender, out string response) + { + if (!sender.CheckPermission(PlayerPermissions.ServerConfigs, out response)) + { + return false; + } + + int pluginCount = PluginLoader.Plugins.Count; + if (pluginCount == 0) + { + response = "No LabAPI plugins installed to reload configs for."; + return false; + } + + StringBuilder sb = StringBuilderPool.Shared.Rent(); + sb.AppendLine($"Reloading configs for {pluginCount} plugin{(pluginCount == 1 ? string.Empty : "s")}"); + + int successCount = 0; + bool success = true; + foreach (Plugin plugin in PluginLoader.Plugins.Keys) + { + try + { + plugin.LoadConfigs(); + successCount++; + } + catch (Exception ex) + { + sb.AppendLine($"Failed to reload configs for plugin {plugin} with Exception:\n{ex}"); + success = false; + } + } + + sb.AppendLine($"Successfully reloaded configs for {(successCount == PluginLoader.Plugins.Count ? "all" : $"{successCount}/{PluginLoader.Plugins.Count}")} plugins."); + response = sb.ToString(); + StringBuilderPool.Shared.Return(sb); + + return success; + } +} diff --git a/LabApi/Loader/Features/Commands/Reload/ReloadParentCommand.cs b/LabApi/Loader/Features/Commands/Reload/ReloadParentCommand.cs new file mode 100644 index 00000000..d7eaf6d0 --- /dev/null +++ b/LabApi/Loader/Features/Commands/Reload/ReloadParentCommand.cs @@ -0,0 +1,30 @@ +using CommandSystem; +using System; +using static LabApi.Loader.Features.Commands.Extensions.CommandExtensions; + +namespace LabApi.Loader.Features.Commands.Reload; + +/// +/// Reload parent command used for all LabAPI reload related sub commands. +/// +[CommandHandler(typeof(LabApiParentCommand))] +public class ReloadParentCommand : ParentCommand +{ + /// + public override string Command => "reload"; + + /// + public override string[] Aliases => ["r", "rl"]; + + /// + public override string Description => "Parent command for all reloading related sub commands."; + + /// + public override void LoadGeneratedCommands() + { + } + + /// + protected override bool ExecuteParent(ArraySegment arguments, ICommandSender sender, out string response) + => ListSubCommands(this, arguments, out response); +} diff --git a/LabApi/Loader/Features/Configuration/LabApiConfig.cs b/LabApi/Loader/Features/Configuration/LabApiConfig.cs index f01466ac..47bea231 100644 --- a/LabApi/Loader/Features/Configuration/LabApiConfig.cs +++ b/LabApi/Loader/Features/Configuration/LabApiConfig.cs @@ -1,6 +1,6 @@ -using System.Collections.Generic; +using LabApi.Loader.Features.Paths; +using System.Collections.Generic; using System.ComponentModel; -using LabApi.Loader.Features.Paths; namespace LabApi.Loader.Features.Configuration; @@ -13,11 +13,18 @@ public class LabApiConfig /// List of dependency paths relative to . /// [Description("List of dependency paths relative to the Dependencies folder to load from. Use $port to load from the server port's folder.")] - public List DependencyPaths { get; set; } = new() { "global", "$port" }; + public List DependencyPaths { get; set; } = ["global", "$port"]; /// /// List of plugin paths relative to . /// [Description("List of plugin paths relative to the Plugins folder to load from. Use $port to load from the server port's folder.")] - public List PluginPaths { get; set; } = new() { "global", "$port" }; -} \ No newline at end of file + public List PluginPaths { get; set; } = ["global", "$port"]; + + /// + /// Whether to allow loading plugins even if they were built for a different major version of LabAPI. + /// + /// + [Description("Whether to allow loading plugins even if they were built for a different major version of LabAPI.")] + public bool LoadUnsupportedPlugins { get; set; } +} diff --git a/LabApi/Loader/Features/Misc/AssemblyUtils.cs b/LabApi/Loader/Features/Misc/AssemblyUtils.cs index a4b9f5d9..04224c83 100644 --- a/LabApi/Loader/Features/Misc/AssemblyUtils.cs +++ b/LabApi/Loader/Features/Misc/AssemblyUtils.cs @@ -65,8 +65,9 @@ public static bool HasMissingDependencies(Assembly assembly, string assemblyPath public static IEnumerable GetLoadedAssemblies() { return AppDomain.CurrentDomain.GetAssemblies().Select(NameSelector); + // We will use this selector to format the assembly names to the format we want. - string NameSelector(Assembly assembly) => FormatAssemblyName(assembly.GetName()); + static string NameSelector(Assembly assembly) => FormatAssemblyName(assembly.GetName()); } /// @@ -76,7 +77,7 @@ public static IEnumerable GetLoadedAssemblies() /// A formatted with the missing dependencies. public static IEnumerable GetMissingDependencies(Assembly assembly) { - IEnumerable loadedAssemblies = GetLoadedAssemblies(); + HashSet loadedAssemblies = GetLoadedAssemblies().ToHashSet(); // Using the same format, we will get the missing dependencies. return assembly.GetReferencedAssemblies().Select(FormatAssemblyName).Where(name => !loadedAssemblies.Contains(name)); } @@ -85,6 +86,7 @@ public static IEnumerable GetMissingDependencies(Assembly assembly) /// Resolves embedded resources from the specified . /// /// The assembly to resolve embedded resources from. + /// This method loads each DLL if no such assembly with the same name has been loaded into the current AppDomain yet. public static void ResolveEmbeddedResources(Assembly assembly) { const string dllExtension = ".dll"; @@ -100,6 +102,7 @@ public static void ResolveEmbeddedResources(Assembly assembly) // If the resource is a dll, we load it as an embedded dll. LoadEmbeddedDll(assembly, resourceName); } + // We check if the resource is a compressed dll. else if (resourceName.EndsWith(compressedDllExtension, StringComparison.OrdinalIgnoreCase)) { @@ -110,39 +113,50 @@ public static void ResolveEmbeddedResources(Assembly assembly) } /// - /// Loads an embedded dll from the specified . + /// Loads an embedded dll from the specified if no such assembly with the same name has been loaded. /// /// The assembly to load the embedded dll from. /// The resource name of the embedded dll. + /// The name check only checks for the of the . public static void LoadEmbeddedDll(Assembly target, string name) { // We try to get the data stream of the specified resource name. if (!TryGetDataStream(target, name, out Stream? dataStream)) + { return; + } - // We copy the data stream to a memory stream and load the assembly from the memory stream. - using MemoryStream stream = new(); - dataStream.CopyTo(stream); - Assembly.Load(stream.ToArray()); + string path = Path.GetTempFileName(); + using (FileStream file = File.Create(path)) + { + dataStream.CopyTo(file); + } + LoadAssemblyIfMissing(path); } /// - /// Loads a compressed embedded dll from the specified . + /// Loads a compressed embedded dll from the specified if no such assembly with the same name has been loaded. /// /// The assembly to load the compressed embedded dll from. /// The resource name of the compressed embedded dll. + /// The name check only checks for the of the . public static void LoadCompressedEmbeddedDll(Assembly target, string name) { // We try to get the data stream of the specified resource name. if (!TryGetDataStream(target, name, out Stream? dataStream)) + { return; + } + + string path = Path.GetTempFileName(); + + using (DeflateStream stream = new(dataStream, CompressionMode.Decompress)) + using (FileStream file = File.Create(path)) + { + stream.CopyTo(file); + } - // We decompress the data stream and load the assembly from the memory stream. - using DeflateStream stream = new(dataStream, CompressionMode.Decompress); - // We use a memory stream to load the assembly from the decompressed data stream. - using MemoryStream memStream = new(); - stream.CopyTo(memStream); - Assembly.Load(memStream.ToArray()); + LoadAssemblyIfMissing(path); } /// @@ -159,7 +173,9 @@ public static bool TryGetDataStream(Assembly target, string name, [NotNullWhen(t // If the data stream is not null, we successfully retrieved the data stream and therefore return true. if (dataStream is not null) + { return true; + } // If the data stream is null, we log an error message and return false. Logger.Error($"{LoggerPrefix} Unable to resolve {name} Stream was null"); @@ -180,4 +196,22 @@ public static bool TryGetLoadedAssembly(this Plugin plugin, out Assembly assembl // Used for missing assembly comparisons. private static string FormatAssemblyName(AssemblyName assemblyName) => $"{assemblyName.Name} v{assemblyName.Version}"; + + private static void LoadAssemblyIfMissing(string path) + { + try + { + AssemblyName? name = AssemblyName.GetAssemblyName(path); + + // Only check name to avoid identity problems + if (name != null && AppDomain.CurrentDomain.GetAssemblies().All(e => e.GetName().Name != name.Name)) + { + PluginLoader.Dependencies.Add(Assembly.Load(File.ReadAllBytes(path))); + } + } + finally + { + File.Delete(path); + } + } } \ No newline at end of file diff --git a/LabApi/Loader/Features/Plugins/Configuration/Properties.cs b/LabApi/Loader/Features/Plugins/Configuration/Properties.cs index 5706fb11..0e13acf9 100644 --- a/LabApi/Loader/Features/Plugins/Configuration/Properties.cs +++ b/LabApi/Loader/Features/Plugins/Configuration/Properties.cs @@ -1,3 +1,4 @@ +using LabApi.Loader.Features.Plugins.Enums; using System.ComponentModel; namespace LabApi.Loader.Features.Plugins.Configuration; @@ -18,4 +19,10 @@ public class Properties /// [Description("Whether or not the plugin is enabled.")] public bool IsEnabled { get; set; } = true; -} \ No newline at end of file + + /// + /// Whether to allow loading the plugin even if it was built for a different major version of LabAPI. + /// + [Description("""Whether to allow loading the plugin even if it was built for a different major version of LabAPI. "Default" = use port-specific config; "True"/"Enabled" = load if unsupported; "False"/"Disabled" = do not load if unsupported""")] + public OptionalBoolean UnsupportedLoading { get; set; } = OptionalBoolean.Default; +} diff --git a/LabApi/Loader/Features/Plugins/Enums/LoadPriority.cs b/LabApi/Loader/Features/Plugins/Enums/LoadPriority.cs index 46632eac..557bc9a2 100644 --- a/LabApi/Loader/Features/Plugins/Enums/LoadPriority.cs +++ b/LabApi/Loader/Features/Plugins/Enums/LoadPriority.cs @@ -34,5 +34,5 @@ public enum LoadPriority : byte /// These plugins are loaded last. /// We recommend using it in plugins which require plugins as dependencies. ///
- Lowest = Priority.Lowest + Lowest = Priority.Lowest, } \ No newline at end of file diff --git a/LabApi/Loader/Features/Plugins/Enums/OptionalBoolean.cs b/LabApi/Loader/Features/Plugins/Enums/OptionalBoolean.cs new file mode 100644 index 00000000..3295ab49 --- /dev/null +++ b/LabApi/Loader/Features/Plugins/Enums/OptionalBoolean.cs @@ -0,0 +1,28 @@ +namespace LabApi.Loader.Features.Plugins.Enums; + +/// +/// Represents values that specify whether a feature should be activated. +/// +public enum OptionalBoolean +{ + /// + /// Uses default behavior, specified in the feature's implementation or in a broader scope. + /// + Default = -1, + + /// + /// Overrides default behavior to disable the feature. + /// + False = 0, + + /// + /// Overrides default behavior to enable the feature. + /// + True = 1, + + /// + Enabled = True, + + /// + Disabled = False, +} diff --git a/LabApi/Loader/Features/Plugins/Plugin.cs b/LabApi/Loader/Features/Plugins/Plugin.cs index d6fdd7e1..b85e472a 100644 --- a/LabApi/Loader/Features/Plugins/Plugin.cs +++ b/LabApi/Loader/Features/Plugins/Plugin.cs @@ -39,6 +39,18 @@ public abstract class Plugin ///
public virtual LoadPriority Priority { get; } = LoadPriority.Medium; + /// + /// Whether this plugin is considered transparent.
+ /// A plugin can be marked as transparent if the server’s modifications are strictly limited to non-intrusive features that do not affect gameplay balance or make significant alterations to the user interface. + /// Examples of transparent modifications are: admin tools, automated timed broadcasts for tips, message of the day or other administrative utilities.
+ /// For more information, see article 5.2 in the official documentation: https://scpslgame.com/csg. + ///
+ /// + /// You can keep using the 'transparently modded' flag during occasional short events organized and supervised by + /// Server Staff, regardless of the Modifications used for these events. + /// + public virtual bool IsTransparent { get; } = false; + /// /// The of the . /// @@ -63,10 +75,12 @@ public abstract class Plugin /// /// Called before the is enabled. - /// + ///
/// Commonly used to load configurations, or any data files before the plugin is enabled. ///
- public virtual void LoadConfigs() { } + public virtual void LoadConfigs() + { + } /// public override string ToString() => $"'{Name}', Version: {Version}, Author: '{Author}'"; diff --git a/LabApi/Loader/Features/Plugins/PluginTConfig.cs b/LabApi/Loader/Features/Plugins/Plugin{TConfig}.cs similarity index 100% rename from LabApi/Loader/Features/Plugins/PluginTConfig.cs rename to LabApi/Loader/Features/Plugins/Plugin{TConfig}.cs diff --git a/LabApi/Loader/Features/Yaml/CustomConverters/CustomColor32Converter.cs b/LabApi/Loader/Features/Yaml/CustomConverters/CustomColor32Converter.cs index af58a713..821d49e4 100644 --- a/LabApi/Loader/Features/Yaml/CustomConverters/CustomColor32Converter.cs +++ b/LabApi/Loader/Features/Yaml/CustomConverters/CustomColor32Converter.cs @@ -18,7 +18,9 @@ public object ReadYaml(IParser parser, Type type) string colorText = scalar.Value; if (!ColorUtility.TryParseHtmlString(colorText, out Color color)) + { throw new ArgumentException($"Unable to parse {nameof(Color32)} value of {colorText}"); + } return (Color32)color; } @@ -26,8 +28,8 @@ public object ReadYaml(IParser parser, Type type) /// public void WriteYaml(IEmitter emitter, object? value, Type type) { - Color32 color = (Color32)value; - emitter.Emit(new Scalar(color.ToHex())); + Color32? color = (Color32?)value; + emitter.Emit(new Scalar(color?.ToHex() ?? Color.white.ToHex())); } /// @@ -36,4 +38,3 @@ public bool Accepts(Type type) return type == typeof(Color32); } } - diff --git a/LabApi/Loader/Features/Yaml/CustomConverters/CustomColorConverter.cs b/LabApi/Loader/Features/Yaml/CustomConverters/CustomColorConverter.cs index d755c349..06c3c6a5 100644 --- a/LabApi/Loader/Features/Yaml/CustomConverters/CustomColorConverter.cs +++ b/LabApi/Loader/Features/Yaml/CustomConverters/CustomColorConverter.cs @@ -15,7 +15,6 @@ namespace LabApi.Loader.Features.Yaml.CustomConverters; ///
public class CustomColorConverter : IYamlTypeConverter { - /// public object? ReadYaml(IParser parser, Type type) { @@ -28,22 +27,23 @@ public class CustomColorConverter : IYamlTypeConverter for (int i = 0; i <= 3; i++) { if (!parser.TryReadMapping(out string key, out string val)) + { throw new ArgumentException($"Unable to parse {nameof(Color)}, no component at index {i} provided"); + } - if (!(key is "r" or "g" or "b" or "a")) + if (key is not ("r" or "g" or "b" or "a")) + { throw new ArgumentException($"Unable to parse {nameof(Color)}, invalid component name {key}. Only 'r', 'g', 'b' and 'a' are allowed"); + } storedValues[key] = float.Parse(val, CultureInfo.InvariantCulture); } + parser.Consume(); - Color value = new Color(storedValues["r"], storedValues["g"], storedValues["b"], storedValues["a"]); + Color value = new(storedValues["r"], storedValues["g"], storedValues["b"], storedValues["a"]); return value; } - catch (ArgumentException) - { - throw; - } finally { DictionaryPool.Release(storedValues); @@ -53,7 +53,7 @@ public class CustomColorConverter : IYamlTypeConverter /// public void WriteYaml(IEmitter emitter, object? value, Type type) { - Color color = (Color)value; + Color color = (Color?)value ?? Color.white; emitter.Emit(new MappingStart(AnchorName.Empty, TagName.Empty, isImplicit: true, MappingStyle.Block)); emitter.EmitMapping("r", color.r.ToString(CultureInfo.InvariantCulture)); diff --git a/LabApi/Loader/Features/Yaml/CustomConverters/CustomQuaternionConverter.cs b/LabApi/Loader/Features/Yaml/CustomConverters/CustomQuaternionConverter.cs new file mode 100644 index 00000000..bc439654 --- /dev/null +++ b/LabApi/Loader/Features/Yaml/CustomConverters/CustomQuaternionConverter.cs @@ -0,0 +1,75 @@ +using LabApi.Loader.Features.Yaml.Extensions; +using System; +using System.Collections.Generic; +using System.Globalization; +using UnityEngine; +using UnityEngine.Pool; +using YamlDotNet.Core; +using YamlDotNet.Core.Events; +using YamlDotNet.Serialization; + +namespace LabApi.Loader.Features.Yaml.CustomConverters; + +/// +/// A custom class for serializing/deserializing as euler angles. +/// +public class CustomQuaternionConverter : IYamlTypeConverter +{ + /// + public object? ReadYaml(IParser parser, Type type) + { + parser.Consume(); + + Dictionary storedValues = DictionaryPool.Get(); + + try + { + for (int i = 0; i <= 2; i++) + { + if (!parser.TryReadMapping(out string key, out string val)) + { + throw new ArgumentException($"Unable to parse {nameof(Quaternion)}, no component at index {i} provided"); + } + + if (!(key is "x" or "y" or "z")) + { + throw new ArgumentException($"Unable to parse {nameof(Quaternion)}, invalid component name {key}. Only 'x', 'y' and 'z' euler angles are allowed"); + } + + storedValues[key] = float.Parse(val, CultureInfo.InvariantCulture); + } + + parser.Consume(); + + Quaternion value = Quaternion.Euler(storedValues["x"], storedValues["y"], storedValues["z"]); + return value; + } + catch (ArgumentException) + { + throw; + } + finally + { + DictionaryPool.Release(storedValues); + } + } + + /// + public void WriteYaml(IEmitter emitter, object? value, Type type) + { + Vector3 rotation = ((Quaternion?)value)?.eulerAngles ?? Vector3.zero; + emitter.Emit(new MappingStart(AnchorName.Empty, TagName.Empty, isImplicit: true, MappingStyle.Block)); + + emitter.EmitMapping("x", rotation.x.ToString(CultureInfo.InvariantCulture)); + emitter.EmitMapping("y", rotation.y.ToString(CultureInfo.InvariantCulture)); + emitter.EmitMapping("z", rotation.z.ToString(CultureInfo.InvariantCulture)); + + emitter.Emit(new MappingEnd()); + } + + /// + public bool Accepts(Type type) + { + return type == typeof(Quaternion); + } +} diff --git a/LabApi/Loader/Features/Yaml/CustomConverters/CustomVectorConverter.cs b/LabApi/Loader/Features/Yaml/CustomConverters/CustomVectorConverter.cs index 59dcb3a2..49bfdd9f 100644 --- a/LabApi/Loader/Features/Yaml/CustomConverters/CustomVectorConverter.cs +++ b/LabApi/Loader/Features/Yaml/CustomConverters/CustomVectorConverter.cs @@ -15,7 +15,6 @@ namespace LabApi.Loader.Features.Yaml.CustomConverters; ///
public class CustomVectorConverter : IYamlTypeConverter { - /// public object? ReadYaml(IParser parser, Type type) { @@ -29,16 +28,19 @@ public class CustomVectorConverter : IYamlTypeConverter while (!parser.TryConsume(out MappingEnd _)) { if (!parser.TryReadMapping(out string key, out string val)) + { throw new ArgumentException($"Unable to parse Vector, no component at index {idx} provided"); + } - - if (!(key is "x" or "y" or "z" or "w")) + if (key is not ("x" or "y" or "z" or "w")) + { throw new ArgumentException($"Unable to parse Vector, invalid component name {key}. Only 'x' 'y' 'z' and 'w' are allowed"); - + } if (storedValues.ContainsKey(key)) + { throw new ArgumentException($"Unable to parse Vector, duplicate component {key}"); - + } storedValues[key] = float.Parse(val, CultureInfo.InvariantCulture); idx++; @@ -49,19 +51,17 @@ public class CustomVectorConverter : IYamlTypeConverter 2 => new Vector2(storedValues["x"], storedValues["y"]), 3 => new Vector3(storedValues["x"], storedValues["y"], storedValues["z"]), 4 => new Vector4(storedValues["x"], storedValues["y"], storedValues["z"], storedValues["w"]), - _ => throw new ArgumentException($"Unable to deserialize vector with {storedValues.Count} components") + _ => throw new ArgumentException($"Unable to deserialize vector with {storedValues.Count} components"), }; Type createdType = result.GetType(); if (createdType != type) + { throw new ArgumentException($"Attempting to deserialize {createdType.Name} for config type of {type.Name}"); + } return result; } - catch (ArgumentException) - { - throw; - } finally { DictionaryPool.Release(storedValues); diff --git a/LabApi/Loader/Features/Yaml/Extensions/YamlMappingExtensions.cs b/LabApi/Loader/Features/Yaml/Extensions/YamlMappingExtensions.cs index 7160d825..4e715bcc 100644 --- a/LabApi/Loader/Features/Yaml/Extensions/YamlMappingExtensions.cs +++ b/LabApi/Loader/Features/Yaml/Extensions/YamlMappingExtensions.cs @@ -26,14 +26,16 @@ public static void EmitMapping(this IEmitter emitter, string key, string value) /// This parser to read from. /// The key value. /// The value. - /// Whether was the kvp succesfully parsed. + /// Whether was the kvp successfully parsed. public static bool TryReadMapping(this IParser parser, out string key, out string value) { key = string.Empty; value = string.Empty; if (!parser.TryConsume(out Scalar keyScalar) || !parser.TryConsume(out Scalar valueScalar)) + { return false; + } key = keyScalar.Value.Trim(); value = valueScalar.Value.Trim(); diff --git a/LabApi/Loader/Features/Yaml/YamlConfigParser.cs b/LabApi/Loader/Features/Yaml/YamlConfigParser.cs index 8b6f58ee..b6afb644 100644 --- a/LabApi/Loader/Features/Yaml/YamlConfigParser.cs +++ b/LabApi/Loader/Features/Yaml/YamlConfigParser.cs @@ -1,7 +1,7 @@ -using YamlDotNet.Serialization.NamingConventions; -using YamlDotNet.Serialization; +using LabApi.Loader.Features.Yaml.CustomConverters; using Serialization; -using LabApi.Loader.Features.Yaml.CustomConverters; +using YamlDotNet.Serialization; +using YamlDotNet.Serialization.NamingConventions; using CommentsObjectGraphVisitor = Serialization.CommentsObjectGraphVisitor; namespace LabApi.Loader.Features.Yaml; @@ -15,14 +15,15 @@ public static class YamlConfigParser /// Static yaml serializer instance. ///
public static ISerializer Serializer { get; } = new SerializerBuilder() - .WithEmissionPhaseObjectGraphVisitor((EmissionPhaseObjectGraphVisitorArgs visitor) => new CommentsObjectGraphVisitor(visitor.InnerVisitor)) - .WithTypeInspector((ITypeInspector typeInspector) => new CommentGatheringTypeInspector(typeInspector)) + .WithEmissionPhaseObjectGraphVisitor(visitor => new CommentsObjectGraphVisitor(visitor.InnerVisitor)) + .WithTypeInspector(typeInspector => new CommentGatheringTypeInspector(typeInspector)) .WithNamingConvention(UnderscoredNamingConvention.Instance) .DisableAliases() .IgnoreFields() .WithTypeConverter(new CustomVectorConverter()) .WithTypeConverter(new CustomColor32Converter()) .WithTypeConverter(new CustomColorConverter()) + .WithTypeConverter(new CustomQuaternionConverter()) .Build(); /// @@ -34,5 +35,6 @@ public static class YamlConfigParser .WithTypeConverter(new CustomVectorConverter()) .WithTypeConverter(new CustomColor32Converter()) .WithTypeConverter(new CustomColorConverter()) + .WithTypeConverter(new CustomQuaternionConverter()) .Build(); } diff --git a/LabApi/Loader/PluginLoader.cs b/LabApi/Loader/PluginLoader.cs index 07f15392..04a75ddd 100644 --- a/LabApi/Loader/PluginLoader.cs +++ b/LabApi/Loader/PluginLoader.cs @@ -1,17 +1,19 @@ +using LabApi.Features; using LabApi.Features.Console; +using LabApi.Features.Permissions; +using LabApi.Features.Permissions.Providers; +using LabApi.Features.Wrappers; +using LabApi.Loader.Features.Configuration; using LabApi.Loader.Features.Misc; using LabApi.Loader.Features.Paths; using LabApi.Loader.Features.Plugins; -using LabApi.Loader.Features.Configuration; +using LabApi.Loader.Features.Plugins.Enums; +using LabApi.Loader.Features.Yaml; using System; using System.Collections.Generic; using System.IO; using System.Linq; using System.Reflection; -using LabApi.Features.Permissions; -using LabApi.Features.Permissions.Providers; -using LabApi.Features.Wrappers; -using LabApi.Loader.Features.Yaml; namespace LabApi.Loader; @@ -58,7 +60,9 @@ public static void Initialize() { // If the loader has already been initialized, we skip the initialization. if (Initialized) + { return; + } Initialized = true; @@ -73,9 +77,13 @@ public static void Initialize() // We first load all the dependencies and store them in the dependencies list LoadAllDependencies(); + // Then we load all the plugins and enable them LoadAllPlugins(); + // Resolve the server modded transparency flag + ResolveTransparentlyModdedFlag(); + // We also register the default permissions provider PermissionsManager.RegisterProvider(); } @@ -99,7 +107,7 @@ public static void LoadAllDependencies() Directory.CreateDirectory(fullPath); - LoadDependencies(new DirectoryInfo(fullPath).GetFiles(DllSearchPattern)); + LoadDependencies(new DirectoryInfo(fullPath).GetFiles(DllSearchPattern, SearchOption.AllDirectories)); } } @@ -148,12 +156,14 @@ public static void LoadAllPlugins() Directory.CreateDirectory(fullPath); if (Directory.Exists(fullPath)) - LoadPlugins(new DirectoryInfo(fullPath).GetFiles(DllSearchPattern)); + { + LoadPlugins(new DirectoryInfo(fullPath).GetFiles(DllSearchPattern, SearchOption.AllDirectories)); + } } // Then we finally enable all the plugins Logger.Info($"{LoggerPrefix} Enabling all plugins"); - EnablePlugins(Plugins.Keys.OrderBy(plugin => plugin.Priority)); + EnablePlugins(Plugins.Keys.OrderBy(static plugin => plugin.Priority)); } /// @@ -162,7 +172,7 @@ public static void LoadAllPlugins() /// The collection of assemblies to load. public static void LoadPlugins(IEnumerable files) { - List<(FileInfo File, Assembly Assembly)> plugins = []; + List<(string Path, Assembly Assembly)> plugins = []; foreach (FileInfo file in files) { @@ -173,12 +183,13 @@ public static void LoadPlugins(IEnumerable files) // We load the assembly from the specified file. Assembly pluginAssembly = pdb.Exists + // In the case that the PDB file exists, we load the assembly with the PDB file. ? Assembly.Load(File.ReadAllBytes(file.FullName), File.ReadAllBytes(pdb.FullName)) + // Otherwise, we load the assembly without any debug information. : Assembly.Load(File.ReadAllBytes(file.FullName)); - - plugins.Add((file, pluginAssembly)); + plugins.Add((file.FullName, pluginAssembly)); } catch (Exception e) { @@ -187,42 +198,32 @@ public static void LoadPlugins(IEnumerable files) } } - foreach ((FileInfo file, Assembly assembly) in plugins) + foreach ((string path, Assembly assembly) in plugins) { try { - // If the assembly has missing dependencies, we skip it. - if (AssemblyUtils.HasMissingDependencies(assembly, file.FullName, out Type[]? types)) - continue; - - InstantiatePlugins(types, assembly, file.FullName); + AssemblyUtils.ResolveEmbeddedResources(assembly); } catch (Exception e) { - Logger.Error($"{LoggerPrefix} Couldn't load the plugin inside '{file.FullName}'"); + Logger.Error($"{LoggerPrefix} Failed to resolve embedded resources for assembly '{path}'"); + LogMissingDependencies(assembly); Logger.Error(e); } } - } - private static void InstantiatePlugins(Type[] types, Assembly assembly, string filePath) - { - foreach (Type type in types) + foreach ((string path, Assembly assembly) in plugins) { - // We check if the type is derived from Plugin. - if (!type.IsSubclassOf(typeof(Plugin))) - continue; - - // We create an instance of the type and check if it was successfully created. - if (Activator.CreateInstance(type) is not Plugin plugin) - continue; - - // Set the file path - plugin.FilePath = filePath; - - // In that case, we add the plugin to the plugins list and log that it has been loaded. - Plugins.Add(plugin, assembly); - Logger.Info($"{LoggerPrefix} Successfully loaded {plugin.Name}"); + try + { + InstantiatePlugins(assembly.GetTypes(), assembly, path); + } + catch (Exception e) + { + Logger.Error($"{LoggerPrefix} Couldn't load the plugin inside '{path}'"); + LogMissingDependencies(assembly); + Logger.Error(e); + } } } @@ -236,11 +237,21 @@ public static void EnablePlugins(IEnumerable plugins) { // We try to load the configuration of the plugin if (!plugin.TryLoadProperties()) + { continue; + } // We check if the plugin is enabled if (plugin.Properties?.IsEnabled == false) + { continue; + } + + // We check if the required version is compatible with the installed LabAPI version + if (!ValidateVersion(plugin)) + { + continue; + } // We finally enable the plugin EnablePlugin(plugin); @@ -257,13 +268,13 @@ public static void EnablePlugin(Plugin plugin) { // We mark the server as modded. CustomNetworkManager.Modded = true; - - // We register all the plugin commands - plugin.RegisterCommands(); // We load the configurations of the plugin plugin.LoadConfigs(); + // We register all the plugin commands + plugin.RegisterCommands(); + // We enable the plugin if it is not disabled plugin.Enable(); @@ -307,8 +318,153 @@ private static void LoadLabApiConfig() } } + /// + /// Resolves whether the installed plugins are marked as transparent and sets the flag based on the result. + /// + private static void ResolveTransparentlyModdedFlag() + { + if (Plugins.Count == 0) + { + return; + } + + if (Server.IsTransparentlyModded) + { + return; + } + + bool isTransparent = true; + + foreach (Plugin plugin in Plugins.Keys) + { + if (!plugin.IsTransparent) + { + isTransparent = false; + break; + } + } + + Server.IsTransparentlyModded = isTransparent; + + if (isTransparent) + { + Logger.Raw($"{LoggerPrefix} This server has been flagged as transparently modded by one or more installed plugins. If you believe this is a mistake, please review your installed plugins and contact the plugin developers.", ConsoleColor.Red); + ServerConsole.Update = true; + } + } + private static string ResolvePath(string path) { return path.Replace("$port", Server.Port.ToString()); } -} \ No newline at end of file + + private static void LogMissingDependencies(Assembly assembly) + { + IEnumerable missing = AssemblyUtils.GetMissingDependencies(assembly); + if (missing.Any()) + { + Logger.Error($"{LoggerPrefix} Missing dependencies:\n{string.Join("\n", missing.Select(static x => $"-\t {x}"))}"); + } + } + + private static bool ValidateVersion(Plugin plugin) + { + Version required = plugin.RequiredApiVersion; + + // TODO: Delete (why.....) + if (required == null) + { + return true; + } + + Version current = LabApiProperties.CurrentVersion; + + if (required.Major == current.Major) + { + if (!IsGreaterVersion(required, current)) + { + return true; + } + + Logger.Warn($""" + {LoggerPrefix} Potential issue with plugin {plugin} + It was built for a newer minor/patch version of LabAPI, and might not be able to access some features it depends on. + Are you running an older version of the server? + Current LabAPI version: {LabApiProperties.CompiledVersion} + Required by plugin: {required} + """); + + return true; + } + + string difference = required.Major < current.Major ? "an outdated major version" : "a newer major version"; + + bool shouldLoad = plugin.Properties?.UnsupportedLoading switch + { + OptionalBoolean.True => true, + OptionalBoolean.False => false, + _ => Config.LoadUnsupportedPlugins, + }; + + if (shouldLoad) + { + Logger.Warn($""" + {LoggerPrefix} Forcefully loading unsupported plugin {plugin} + It was built for {difference} of LabAPI, and will likely have degraded functionality. + Current LabAPI version: {LabApiProperties.CompiledVersion} + Required by plugin: {required} + """); + return true; + } + + Logger.Error($""" + {LoggerPrefix} Couldn't enable the plugin {plugin} + It was built for {difference} of LabAPI, and would likely have degraded functionality. + To forcefully load it, set the appropriate property in the plugins's properties.yml file. + To forcefully load all unsupported plugins, set the appropriate property in the LabAPI configuration for the current port (LabApi-{Server.Port}.yml). + Current LabAPI version: {LabApiProperties.CompiledVersion} + Required by plugin: {required} + """); + return false; + } + + private static void InstantiatePlugins(Type[] types, Assembly assembly, string filePath) + { + foreach (Type type in types) + { + // We check if the type is derived from Plugin. + if (!type.IsSubclassOf(typeof(Plugin)) || type.IsAbstract) + { + continue; + } + + // We create an instance of the type and check if it was successfully created. + if (Activator.CreateInstance(type) is not Plugin plugin) + { + continue; + } + + // Set the file path + plugin.FilePath = filePath; + + // In that case, we add the plugin to the plugins list and log that it has been loaded. + Plugins.Add(plugin, assembly); + Logger.Info($"{LoggerPrefix} Successfully loaded {plugin.Name}"); + } + } + + private static bool IsGreaterVersion(Version required, Version current) + { + Version requiredVersion = new( + required.Major, + required.Minor, + required.Build == -1 ? 0 : required.Build, + required.Revision == -1 ? 0 : required.Revision); + Version currentVersion = new( + current.Major, + current.Minor, + current.Build == -1 ? 0 : current.Build, + current.Revision == -1 ? 0 : current.Revision); + return requiredVersion > currentVersion; + } +} diff --git a/LabApi/README.md b/LabApi/README.md new file mode 120000 index 00000000..457d2fe8 --- /dev/null +++ b/LabApi/README.md @@ -0,0 +1 @@ +C:/Users/jesusqc/RiderProjects/LabAPI-Internal/.github/README.md \ No newline at end of file diff --git a/LabApi/stylecop.json b/LabApi/stylecop.json new file mode 100644 index 00000000..c076f363 --- /dev/null +++ b/LabApi/stylecop.json @@ -0,0 +1,14 @@ +{ + "$schema": "https://raw.githubusercontent.com/DotNetAnalyzers/StyleCopAnalyzers/master/StyleCop.Analyzers/StyleCop.Analyzers/Settings/stylecop.schema.json", + "settings": { + "orderingRules": { + "elementOrder": [ "constant", "static", "kind", "accessibility" ], + "systemUsingDirectivesFirst": false, + "usingDirectivesPlacement": "outsideNamespace", + "blankLinesBetweenUsingGroups": "omit" + }, + "maintainabilityRules": { + "topLevelTypes": ["class", "interface", "delegate", "enum", "struct"] + } + } +} diff --git a/NuGet.config b/NuGet.config new file mode 100644 index 00000000..4d736c19 --- /dev/null +++ b/NuGet.config @@ -0,0 +1,7 @@ + + + + + + + diff --git a/README.md b/README.md index be23938e..8aaaa1b0 100644 --- a/README.md +++ b/README.md @@ -1,5 +1,35 @@ -[![GitHub release](https://flat.badgen.net/github/release/northwood-studios/LabAPI/)](https://github.com/northwood-studios/NwPluginAPI/releases/) [![NuGet](https://flat.badgen.net/nuget/v/Northwood.LabAPI/latest)](https://www.nuget.org/packages/Northwood.LabAPI/) [![License](https://flat.badgen.net/github/license/northwood-studios/LabAPI)](https://github.com/northwood-studios/LabAPI/blob/master/LICENSE) [![Discord Invitation](https://flat.badgen.net/discord/members/scpsl?icon=discord)](https://discord.gg/scpsl) -# LabAPI +

+ + + + NW logo + + +

+ +

LabAPI

+
SCP: Secret Laboratory's official server-side modding framework.
+
+ Plugins + - + Docs + - + Report Bug + - + Discord +

+
+ +
+ +[![Version](https://img.shields.io/github/v/release/northwood-studios/LabAPI?sort=semver&style=flat-square&color=8DBBE9&label=Version)]() +[![License](https://img.shields.io/github/license/northwood-studios/LabAPI?style=flat-square&label=License&color=df967f)]() +[![Contributors](https://img.shields.io/github/contributors-anon/northwood-studios/LabAPI?color=90E59A&style=flat-square&label=Contributors)]() +[![GitHub Issues](https://img.shields.io/github/issues/northwood-studios/LabAPI.svg?style=flat-square&label=Issues&color=d77982)](https://github.com/northwood-studios/LabAPI/issues) +[![Discord](https://img.shields.io/discord/330432627649544202?color=738adb&label=Discord&logo=discord&logoColor=white&style=flat-square)](https://discord.gg/scpsl) + +
+ The LabAPI project is **[SCP: Secret Laboratory](https://store.steampowered.com/app/700330/SCP_Secret_Laboratory/)**'s official server-side plugin loader and framework. It facilitates development of plugins by providing wrappers and events around various game mechanics found throughout the game. ## Documentation diff --git a/StyleCopAnalyzers.ruleset b/StyleCopAnalyzers.ruleset new file mode 100644 index 00000000..c1e8677f --- /dev/null +++ b/StyleCopAnalyzers.ruleset @@ -0,0 +1,13 @@ + + + + + + + + + + + + + \ No newline at end of file