Compare commits

...

538 Commits

Author SHA1 Message Date
MSWS
cab156184c Tweak credit penalty 2025-10-02 11:04:09 -07:00
MSWS
9ee69a0b28 feat: Add credits given for killing / identifying +semver:minor
```
- Refactor balance deduction in Shop.cs to use `AddBalance` method for improved consistency and added player notification for successful purchases.
- Enhance BuyCommand.cs by updating Execute method to return Task.FromResult, adding a health check, and modifying item search logic for better accuracy.
- Update PlayerKillListener.cs to extend from BaseListener, integrate ShopAPI, and add methods for handling on-kill and body identification events with balance adjustments.
- Use JetBrains.Annotations in RoleAssignCreditor.cs for potential external or reflective method use, adding UsedImplicitly attribute for OnRoleAssign method.
- Extend ShopMsgs.cs and en.yml with new purchase success messages including item names, improving player feedback.
```
2025-10-02 11:03:03 -07:00
MSWS
e529229200 Update licenses 2025-10-01 23:46:52 -07:00
MSWS
e7dc5c02fe feat: Add camouflage item +semver:minor (resolves #73)
- Add `CamouflageItem` class for managing camouflage items in the game
- Implement `AddCamoServices` in service collection extension for mod behavior
- Introduce configuration loading for camouflage settings with `IStorage<CamoConfig>`
- Provide localization for item name and description
- Implement purchasing logic: visibility settings and ownership check in `CamouflageItem`
- Add "Camouflage" item and description to the language file
- Expand shop services to include camouflage features via `AddCamoServices`
- Establish `CamoConfig` in `ShopAPI` with default pricing and visibility properties
- Create `CamoMsgs` class for managing camouflage item messages
2025-10-01 23:34:05 -07:00
MSWS
522e42a5ff Reformat & Cleanup 2025-10-01 23:26:30 -07:00
MSWS
871500fbdc Cleanup unused lines 2025-10-01 23:21:39 -07:00
MSWS
f023d36aa9 Update CS2 impl 2025-10-01 23:10:58 -07:00
MSWS
a185b217e0 feat: Add traitor gloves item and reorganize configs. (resolves #81)
- Add new "Gloves" item to traitor shop with localization and descriptions
- Allow modification of `Killer` property in `IBody.cs` for enhanced gameplay flexibility
- Reorganize configuration files under relevant directories for better clarity (e.g., HealthStationConfig, DnaScannerConfig)
- Introduce `GlovesListener` class to handle event-driven interactions for the "Gloves" item
- Implement traitor-specific configurations and services for items like C4 and gloves, including default pricing and usage limits
2025-10-01 23:09:43 -07:00
MSWS
dbfd360c6c feat: Add M4A1 shop item +semver:minor (resolves #71)
```
Add M4A1 Item to Shop with Configuration and Localization

- Add TTT/Shop/Items/M4A1/M4A1Msgs.cs to manage localized messages for the M4A1 item.
- Update TTT/Shop/lang/en.yml with a new shop item "M4A1 Rifle and USP-S" and its description.
- Modify TTT/Shop/ShopServiceCollection.cs to include M4A1 services and adjust service ordering for better organization.
- Introduce TTT/ShopAPI/Configs/M4A1Config.cs for setting up the M4A1 item configuration, including price and weapon slots.
- Create TTT/Shop/Items/M4A1/M4A1ShopItem.cs to define the M4A1 shop item with purchase and inventory management logic.
```
2025-10-01 22:47:05 -07:00
MSWS
4a64741a8e Add CS2-specific configuration of C4 item 2025-10-01 22:20:14 -07:00
MSWS
7372ffda45 feat: Add C4 item for TraitorRole in shop +semver:minor (resolves #79)
- Add C4Msgs class for localization of C4 shop item in the Traitor category
- Introduce C4ShopItem class with methods for purchase, limitations, and role restriction handling
- Update ShopServiceCollection to include C4 service for Traitor role
- Introduce C4Config class for configuration of C4 shop items with various properties
- Add English localization entry for "C4 Explosive" shop item with description
2025-10-01 22:16:03 -07:00
MSWS
9ea9c78208 Remove extra spacing in DNA locale 2025-10-01 22:02:59 -07:00
MSWS
85601f1fc0 feat: Implement configurable sound and localization support
- Add configuration for `UseSound` property in `DamageStationConfig` and `HealthStationConfig`
- Implement localization support in `HealthStation.cs` by replacing hardcoded strings with localized messages
- Introduce `UseSound` abstract property in `StationConfig`
- Update localization files with new shop items and descriptions in `lang/en.yml`
- Create `StationMsgs.cs` to manage station-related item messages via a factory pattern
- Enhance `DamageStation.cs` for internationalization and configurable sound settings
- Annotate unused or implicitly used methods in `StickerListener.cs` with `[UsedImplicitly]`
2025-10-01 22:02:12 -07:00
MSWS
ddf52f057d Update from main 2025-10-01 21:50:19 -07:00
Isaac
c2ecba1847 Merge branch 'main' into dev 2025-10-01 20:39:01 -07:00
Isaac
354ccf2fbe Update TTT/Shop/Items/Detective/Stickers/Stickers.cs
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
Signed-off-by: Isaac <git@msws.xyz>
2025-10-01 20:38:03 -07:00
Isaac
9d1a7f5618 feat: Integrate ShopAPI and add station item features +semver:minor (resolves #84) (#92)
```
- Integrate ShopAPI into various components including PlayerPurchaseItemEvent, DnaScanner, and multiple stations for improved shop functionalities.
- Introduce new HealthStationConfig and DamageStationConfig for configuring health and damage-related station items.
- Update CS2 project to target .NET 8.0 and enable advanced C# features, while removing outdated folder references for streamlined project structure.
- Correct namespace declarations across multiple files, enhancing consistency and organizational clarity within the codebase.
- Add new or updated commands and extensions, such as SetHealthCommand, to improve player health management and interaction.
- Enhance localization features by importing TTT.Game.lang across various roles, commands, and logging implementations.
- Incorporate new logic in DNA scanning and station interactions, including damage dealing and healing over time based on player proximity.
```
2025-10-01 19:13:36 -07:00
MSWS
ea62b312be Update unit tests 2025-10-01 19:12:10 -07:00
MSWS
6778531312 feat: Integrate ShopAPI and add station item features +semver:minor
```
- Integrate ShopAPI into various components including PlayerPurchaseItemEvent, DnaScanner, and multiple stations for improved shop functionalities.
- Introduce new HealthStationConfig and DamageStationConfig for configuring health and damage-related station items.
- Update CS2 project to target .NET 8.0 and enable advanced C# features, while removing outdated folder references for streamlined project structure.
- Correct namespace declarations across multiple files, enhancing consistency and organizational clarity within the codebase.
- Add new or updated commands and extensions, such as SetHealthCommand, to improve player health management and interaction.
- Enhance localization features by importing TTT.Game.lang across various roles, commands, and logging implementations.
- Incorporate new logic in DNA scanning and station interactions, including damage dealing and healing over time based on player proximity.
```
2025-10-01 19:08:30 -07:00
MSWS
8ab4328d9b Fix YML 2025-10-01 15:01:35 -07:00
MSWS
c5a91f334d refactor: Improve item not found handling and code readability
- Add a new message for item not found in `en.yml` to enhance user error feedback
- Clean up `GiveItemCommand.cs` by importing `TTT.Locale` and removing debug messages
- Improve `CS2AliveSpoofer.cs` readability with better conditional logic and early return handling
- Enhance `BuyCommand.cs` by removing redundant searches and utilizing localization for consistency
- Change `DecayTime` in `DnaScannerConfig.cs` from 3 minutes to 10 seconds for faster testing
2025-10-01 14:55:28 -07:00
MSWS
b2f4474e8f Reformat 2025-10-01 14:39:15 -07:00
Isaac
8aee59a87e Feat/dna (resolves #87) (#91) 2025-10-01 14:21:04 -07:00
MSWS
e27bddf8e2 feat: Implement enhanced DNA scanner messaging +semver:minor
- Clean up `ShopAPI.csproj` by removing redundant project references.
- Remove the DNA Scanner item and its description from the English language file in `Shop`.
- Streamline `DnaScanner.cs` by eliminating an unnecessary using directive.
- Enhance `DnaListener.cs` to improve messaging logic with role information and implement new message templating for DNA scans.
- Refactor `DnaMsgs.cs` by adjusting namespaces and adding message properties for enhanced DNA scan functionalities.
- Update `CS2.csproj` by removing a duplicate project reference.
- Expand `en.yml` in `CS2` with translations for DNA scanner items and messages for DNA scanning, including specific scenarios involving suicide.
2025-10-01 14:17:27 -07:00
MSWS
4514e9baa0 feat: Introduce DNA scanner functionality
- Extend functionality in `DnaListener.cs` by adding dependency injection and enhancing the `OnPropPickup` event handler with player and body checks.
- Add `TimeOfDeath` property to `CS2Body.cs` for improved tracking of body creation time.
- Introduce `DnaScannerServiceCollection` in `DnaScanner.cs` for better service management and mod behavior registration.
- Extend `IBody` interface with `TimeOfDeath` to track deceased player identification time.
- Update `ShopServiceCollection.cs` to integrate `AddDnaScannerServices`, enhancing shop capabilities with DNA scanner features.
2025-10-01 11:23:31 -07:00
MSWS
67755c36c6 Tweak AI prompt and input 2025-09-30 18:25:18 -07:00
MSWS
eaf1ab627e Begin work on adding CS2-specific items
```
- Rename and reorganize directories for DNA-related items to new path under "CS2/Items/DNA"
- Relocate RoleRestrictedItem.cs while maintaining its original functionality
- Move and update DnaListener.cs with a low-priority event handler and add an execution order comment
- Rename BaseItem.cs file path as part of project structure reorganization
- Update CS2.csproj by adding "Items\" folder and correcting duplicate project reference
```
2025-09-30 18:22:13 -07:00
MSWS
57bef00055 Refactor Shop api into its own project, separate from impl 2025-09-30 18:18:07 -07:00
MSWS
7dd6d4dd38 Finalize stickers (resolves #89) 2025-09-30 17:46:52 -07:00
MSWS
f1cce6c230 Fix windows-specific issues 2025-09-30 17:32:42 -07:00
MSWS
922f121009 refactor: Add IIconManager and Sticker features +semver:minor
```
- Rename property `Name` to `Id` across various commands and classes for consistency and clarity, affecting files like `Test/SetRoleCommand.cs`, `GameHandlers/KarmaSyncer.cs`, and `Command/Test/TestCommand.cs`.
- Add new interface `IIconManager` to manage player visibility with methods for handling up to 64 players using a bitmask in `API/Player/IIconManager.cs`.
- Introduce `ShowIconsCommand` and `IndexCommand` classes to enhance game command functionality, leveraging the new `IIconManager` for icon management.
- Implement a new shop item "Stickers" with associated classes `Stickers.cs`, `StickerListener.cs`, and `StickerMsgs.cs`, providing role-revealing capabilities for detective players.
- Refactor shop item and command structures to use a new `BaseItem` abstract class, enhancing code organization and inheritance patterns.
- Update logging in `Plugin/TTT.cs` to use `Id` instead of `Name` for module identification, standardizing log outputs.
- Adjust visibility and color duration settings in `Listeners/ScreenColorApplier.cs` for improved gameplay feedback.
- Refactor service registration and command handling to remove redundancies and improve icon manager integrations in files like `CS2ServiceCollection.cs` and `Command/Test/ScreenColorCommand.cs`.
```
2025-09-30 17:00:57 -07:00
MSWS
2a0924138f Tweak 1-shot weapon defaults 2025-09-30 13:03:30 -07:00
Isaac
a4dc781ee4 Feat/one shot revolver (resolves #66) (#90) 2025-09-30 11:15:24 -07:00
MSWS
935b430769 refactor: Enhance purchase messaging system with localization
- Add new localized messages for shop interactions in `TTT/Shop/lang/en.yml`
- Implement `PurchaseResultExtensions` in `TTT/Shop/Shop/PurchaseResult.cs` to translate purchase outcomes to user-friendly messages
- Streamline and optimize purchase process in `TTT/Shop/Commands/BuyCommand.cs`
- Localize error messages and improve test setup in `TTT/Test/Shop/Commands/BuyTest.cs`
- Update `TTT/Shop/Shop.cs` to use localized messages and enhance error handling logic
2025-09-30 11:13:25 -07:00
MSWS
9dd4414733 Tweak restrictions on deagle config 2025-09-30 10:59:04 -07:00
MSWS
dce4edd6a4 feat: Make friendly fire configurable
```
- Introduce a new configuration variable in `CS2OneShotDeagleConfig.cs` to determine if the shooter should be killed upon friendly fire, and update the `Load` method accordingly.
- Add a static message `SHOP_ITEM_DEAGLE_HIT_FF` in `DeagleMsgs.cs` for handling new Deagle functionality messages.
- Rename "One-Hit Deagle" to "One-Hit Revolver" in `en.yml` and update description and messages for consistency.
- Refactor friendly fire logic in `DeagleDamageListener.cs` by integrating nested conditions and simplifying weapon verification logic for damage events.
- Add `KillShooterOnFF` configuration option in `OneShotDeagle.cs` to manage shooter consequences on friendly fire.
```
2025-09-30 10:57:22 -07:00
MSWS
324711acb9 Working deagle impl +semver:minor 2025-09-30 10:34:47 -07:00
MSWS
85ae2c4210 Add reverse cache to CCPlayerConverter 2025-09-30 09:52:12 -07:00
Isaac
2e6743c25d Miscelleaneous Tweaks
<p dir="auto">This pull request appears to be a development branch merge
 that implements several enhancements and fixes to the TTT (Trouble in 
Terrorist Town) game system. The changes focus on improving weapon 
handling, adding new test coverage, and enhancing player visual
effects.</p>
<ul dir="auto">
<li>Refactors weapon API by renaming <code class="notranslate">Id</code>
property to <code class="notranslate">WeaponId</code> for better
clarity</li>
<li>Implements comprehensive shop and weapon testing infrastructure</li>
<li>Adds screen color effects and player visual enhancements</li>
</ul>
<h3 dir="auto">Reviewed Changes</h3>
<p dir="auto">Copilot reviewed 32 out of 32 changed files in this pull
request and generated 2 comments.</p>
<details open="">
<summary>Show a summary per file</summary>
<markdown-accessiblity-table data-catalyst="">
File | Description
-- | --
TTT/API/IWeapon.cs | Renames weapon identifier property from Id to
WeaponId
TTT/Test/Shop/ShopTests.cs | Adds comprehensive test coverage for shop
functionality
TTT/Test/Shop/Items/DeagleTests.cs | Implements tests for one-shot
deagle weapon behavior
TTT/Test/TestPlayer.cs | Enhances test player with computed IsAlive
property
TTT/CS2/Player/CS2InventoryManager.cs | Adds weapon slot management and
refactors weapon handling
TTT/CS2/Extensions/PlayerExtensions.cs | Implements screen color fade
effects for players
TTT/CS2/Listeners/ScreenColorApplier.cs | Adds role-based screen color
feedback
TTT/Game/Roles/BaseWeapon.cs | Updates weapon class to use WeaponId
property
TTT/Shop/Items/OneShotDeagle/OneShotDeagle.cs | Updates deagle
implementation for new weapon API

</markdown-accessiblity-table></details>
2025-09-28 01:32:07 -07:00
Isaac
5ff27b37e5 Merge branch 'main' into dev 2025-09-28 01:29:38 -07:00
MSWS
1a4e5e3e77 +semver:minor 2025-09-28 01:24:45 -07:00
MSWS
721504f612 Debug out workflow +semver:patch 2025-09-28 01:19:57 -07:00
MSWS
86c24533b5 Test bumping +semver:patch 2025-09-28 01:15:39 -07:00
Isaac
eba49139c2 ci: Implement AI-driven changelog rewriting workflow +ratio (#59)
- Add environment variables and steps for OpenAI API usage in
`.github/workflows/release.yml`
- Retain raw changelog on AI rewrite failure and differentiate naming
- Introduce conditional logic for selective changelog rewriting
- Update GitHub release creation to utilize AI-rewritten changelog when
available
2025-09-28 01:05:24 -07:00
MSWS
d33550a5a4 ci: Enhance release workflow and changelog generation
- Add `fetch-tags: true` to actions/checkout in release workflow to ensure all tags are fetched during checkout.
- Improve tag determination process with lineage-aware strategy and refined pattern matching.
- Change changelog generation to use local git log for better control over commit messages.
- Enhance logic for finding commits for changelog, specifically handling first and subsequent releases.
- Improve error handling and retry mechanism for OpenAI API calls, and refine changelog rewrite logic with fallback strategies.
- Update comment styles for better clarity and organization.
2025-09-28 01:03:57 -07:00
MSWS
453ce77711 ci: Implement AI-driven changelog rewriting workflow +ratio
- Add environment variables and steps for OpenAI API usage in `.github/workflows/release.yml`
- Retain raw changelog on AI rewrite failure and differentiate naming
- Introduce conditional logic for selective changelog rewriting
- Update GitHub release creation to utilize AI-rewritten changelog when available
2025-09-28 00:58:21 -07:00
MSWS
b427dc370e refactor: Remove debug logs and adjust event priorities
- Remove debug logging statements and simplify service registration logic in `ServiceCollectionExtensions.cs`
- Adjust the event handler's priority in `RoundShopClearer.cs` without functional changes
- Update wording in `README.md` for clearer public API usage
- Modify event handler priority in `PlayerStatsTracker.cs` while maintaining existing functionality
- Streamline `IOnlinePlayer.cs` by removing obsolete commented-out code and refining interface properties
- Lower event handler priority in `PlayerActionsLogger.cs` for player kills
2025-09-28 00:46:44 -07:00
MSWS
ede9badbd9 Add additional unit tests for shop 2025-09-28 00:34:55 -07:00
MSWS
5736588484 refactor: Rename Id to WeaponId across the codebase
- Rename property `Id` to `WeaponId` in `IWeapon.cs`, `BaseWeapon.cs`, and `OneShotDeagle.cs` for improved clarity.
- Update weapon removal method in `IInventoryManager.cs` to use `weapon.WeaponId`.
- Refactor `PlayerDamagedEvent.cs` to initialize `Weapon` property with `init` for stricter immutability.
- Revise `IsAlive` logic in `TestPlayer.cs` to adjust `Health` based on `IsAlive` status; deprecate the `Roles` property.
- Add `using` directive and `[UsedImplicitly]` attribute to `DeagleDamageListener.cs` for dependency management and traceability.
- Develop `DeagleTests.cs` to ensure proper functionality of Deagle weapon behaviors using Xunit.
2025-09-28 00:16:28 -07:00
MSWS
8a894c65e8 refactor: Adjust player color handling logic
- Adjust the alpha value handling in `SetColor` method within `PlayerExtensions.cs` to ensure it stays within limits.
- Simplify player color setting in `RoundTimerListener.cs` by using `Color.White` for improved readability.
- Update `BodySpawner.cs` to change player post-death color to fully opaque white and simplify round start color setting using `Color.White`.
2025-09-27 20:30:07 -07:00
MSWS
0634af8ad8 feat: Add weapon slot removal functionality
- Fix typo in comment and clarify kill detection process in `PlayerStatsTracker.cs`
- Add `RemoveWeaponInSlot` method for slot-based weapon removal in `FakeInventoryManager.cs` and update `IInventoryManager.cs` for enhanced functionality
- Reformat `BaseWeapon` constructor for readability and standardize file formatting
- Simplify `CS2Body.cs` API by removing overloaded weapon method and reinforce `IWeapon` interface usage
- Refactor `CS2InventoryManager.cs` for improved weapon management, add methods for slot conversion and weapon removal, and streamline code structure
- Add debug messaging to `DeagleDamageListener.cs` for better runtime clarity on friendly fire and one-shot kill conditions
- Modify `BodySpawner.cs` to incorporate `BaseWeapon` wrapper for improved weapon management without affecting core functionality
- Adjust `OnPlayerKill` event handler priority in `PlayerActionsLogger.cs` to ensure kill logging before game ends
2025-09-27 20:25:53 -07:00
MSWS
9f6c3f7be4 Check player count on round start before starting 2025-09-27 19:07:28 -07:00
MSWS
9eb313e9f1 feat: Introduce screen color features and state command
```
Enhance game management and command structure with new features and optimizations

- Add logic in `PlayerJoinStarting.cs` to handle failure in game instance creation and ensure game starts only upon successful creation.
- Introduce IMessenger service in `CS2GameManager.cs` using dependency injection; add debug logging for the game creation process.
- Implement new behavior for `ScreenColorApplier` in `CS2ServiceCollection.cs` to enhance listening capabilities.
- Create a new `StateCommand` in `StateCommand.cs` to check active game state and implement basic command lifecycle methods.
- Remove "screentext" command and add "state" and "screencolor" commands in `TestCommand.cs` to revamp command options.
- Simplify vector operations in `TextSpawner.cs` by replacing `GetRightVector`; enhance screen text positioning.
- Expand `VectorExtensions.cs` with `ToRight` and `ToUp` methods for better angle-to-vector conversions.
- Remove `ScreenTextCommand.cs` to streamline project and potentially refactor screen text feature.
- Add `ScreenColorApplier` to apply screen color effects upon role assignment, enhancing player interaction experience.
- Introduce `ScreenColorCommand` for player screen color effects with configurable parameters, enriching command functionality.
```
2025-09-26 20:28:35 -07:00
MSWS
9b5563aa8e feat: Refactor text positioning and add screen fade effects
- Refactor `TextSpawner.cs` to improve angle calculations and text positioning with respect to the player.
- Replace static `screenAngle` with local computations for better clarity and maintainability in `TextSpawner.cs`.
- Introduce `angle` object in `TextSpawner.cs` to enhance readability and explicitness in rotation management.
- Add `FadeFlags` enum and implement `ColorScreen` method in `PlayerExtensions.cs` to manage screen color fade effects.
- Enhance color fade handling in `PlayerExtensions.cs` by utilizing `UserMessage` with custom flag settings and improved color configurations.
2025-09-26 18:47:18 -07:00
MSWS
2058d0c780 Start work on screen text 2025-09-26 18:29:59 -07:00
Isaac
ee7f34b435 Bump the nuget group with 1 update (#58)
Pinned System.Text.Json at 8.0.5.

Dependabot will resolve any conflicts with this PR as long as you don't
alter it yourself. You can also trigger a rebase manually by commenting
`@dependabot rebase`.

[//]: # (dependabot-automerge-start)
[//]: # (dependabot-automerge-end)

---

<details>
<summary>Dependabot commands and options</summary>
<br />

You can trigger Dependabot actions by commenting on this PR:
- `@dependabot rebase` will rebase this PR
- `@dependabot recreate` will recreate this PR, overwriting any edits
that have been made to it
- `@dependabot merge` will merge this PR after your CI passes on it
- `@dependabot squash and merge` will squash and merge this PR after
your CI passes on it
- `@dependabot cancel merge` will cancel a previously requested merge
and block automerging
- `@dependabot reopen` will reopen this PR if it is closed
- `@dependabot close` will close this PR and stop Dependabot recreating
it. You can achieve the same result by closing it manually
- `@dependabot show <dependency name> ignore conditions` will show all
of the ignore conditions of the specified dependency
- `@dependabot ignore <dependency name> major version` will close this
group update PR and stop Dependabot creating any more for the specific
dependency's major version (unless you unignore this specific
dependency's major version or upgrade to it yourself)
- `@dependabot ignore <dependency name> minor version` will close this
group update PR and stop Dependabot creating any more for the specific
dependency's minor version (unless you unignore this specific
dependency's minor version or upgrade to it yourself)
- `@dependabot ignore <dependency name>` will close this group update PR
and stop Dependabot creating any more for the specific dependency
(unless you unignore this specific dependency or upgrade to it yourself)
- `@dependabot unignore <dependency name>` will remove all of the ignore
conditions of the specified dependency
- `@dependabot unignore <dependency name> <ignore condition>` will
remove the ignore condition of the specified dependency and ignore
conditions
You can disable automated security fix PRs for this repo from the
[Security Alerts page](https://github.com/MSWS/TTT/network/alerts).

</details>
2025-09-26 18:00:40 -07:00
Isaac
783f6da6dd Merge branch 'main' into dependabot/nuget/Locale/nuget-9df58bc52d 2025-09-26 17:58:41 -07:00
MSWS
f245c61d01 AI is the future! 2025-09-25 22:18:41 -07:00
MSWS
b4076934d8 Fix yml? 2025-09-25 22:15:48 -07:00
MSWS
21b869507b Add GitVersion config, include gamedata in releases 2025-09-25 22:09:43 -07:00
dependabot[bot]
fca81c0577 Bump the nuget group with 1 update
Bumps System.Text.Json from 8.0.0 to 8.0.5

---
updated-dependencies:
- dependency-name: System.Text.Json
  dependency-version: 8.0.5
  dependency-type: direct:production
  dependency-group: nuget
- dependency-name: System.Text.Json
  dependency-version: 8.0.5
  dependency-type: direct:production
  dependency-group: nuget
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-09-26 04:40:30 +00:00
Isaac
db8fe8f069 Bug Fixes, Foundational Work for Shop and Karma (#57) 2025-09-25 21:37:10 -07:00
Isaac
dce6d759a8 Merge branch 'main' into dev 2025-09-25 21:26:55 -07:00
MSWS
f028074939 Tweak karma update interval 2025-09-25 21:26:34 -07:00
MSWS
1d96be0cb0 Remove verbose debug 2025-09-25 21:22:47 -07:00
MSWS
0cbb931aaa Additional buy test command 2025-09-25 21:22:22 -07:00
MSWS
6c2bd538a9 Fix buy tests 2025-09-25 21:20:58 -07:00
MSWS
6b0dcbd42f Resolve log-based test failures 2025-09-25 21:09:00 -07:00
MSWS
c512b60260 Reformat & Cleanup 2025-09-25 21:01:50 -07:00
MSWS
295f2bcad0 Fix compile error 2025-09-25 19:48:57 -07:00
MSWS
5b46fb1282 feat: Introduce player state spoofing feature
```
Implement player state spoofing and enhance body identification

- Introduce `CS2AliveSpoofer` class and `IAliveSpoofer` interface to manage "fake alive" player states in `CombatHandler` and `ForceAliveCommand`.
- Modify `BODY_IDENTIFIED` logic in `GameMsgs.cs` for nullable identifiers, providing a default "Someone" message when missing.
- Update `ForceAliveCommand` and `IdentifyAllCommand` to use new spoofing and identification utilities.
- Enhance body tracking with `BodyTracker` class, integrating event handling improvements for game state changes and body creation.
- Refine `OneShotDeagle` functionality by clearing player's inventory before assigning the weapon, improving game balance.
- Adjust `BodyPickupListener` to use `IBodyTracker` for efficient body management and consolidate event handling logic.
- Update various components to utilize dependency injection and new APIs, improving service management and system robustness.
```
2025-09-25 19:42:50 -07:00
MSWS
4b3d9335b5 Merge branch 'dev' of github.com:MSWS/TTT into dev 2025-09-25 16:36:57 -07:00
MSWS
ec48a9b243 Fix role formatting, pad names (resolves #52 & #56) 2025-09-25 16:36:47 -07:00
MSWS
254e5539b7 Fix role formatting (resolves #52) 2025-09-25 16:35:27 -07:00
MSWS
547228d09a Clarify name in combathandler 2025-09-25 16:23:43 -07:00
MSWS
99e4c6fc07 refactor: Refactor game logic (resolves #51)
- Modify `RoundBasedGame.cs` to improve encapsulation, consistency, and maintainability by refactoring game-ending logic and updating access modifiers for subclassing.
- Implement player data caching in `CS2Player.cs` to enhance performance and improve debug logging capabilities.
- Refactor message formatting in `CS2Messenger.cs` for improved consistency in debug modes.
- Enhance `PlayerConnectionsHandler.cs` by adding asynchronous behavior and a dependency on `IMessenger` for potential future enhancements.
- Add a validity check in `RoundTimerListener.cs` to ensure team scores are only updated with a defined winning role, improving robustness.
- Update `CS2Game.cs` to broadcast notifications for game start states and handle countdowns effectively.
- Introduce `CheckEndConditions()` method in `IGame.cs` interface and deprecate `IsInProgress()` to promote explicit state management.
- Centralize and simplify end game logic in `PlayerCausesEndListener.cs` by implementing `CheckEndConditions()`, eliminating redundant code.
2025-09-25 16:05:48 -07:00
MSWS
52b8d1d2ff refactor: Refactor player leave handling logic and tests (ref: #51)
- Rename test method `Round_EndsWhen_PlayerLeaves` to `Round_EndsWhen_PlayerLeavesAndDies` in `RoundEndingTest.cs` and add `PlayerDiesOnLeaveListener`.
- Improve code efficiency and readability in player iteration and event creation in `PlayerConnectionsHandler.cs`.
- Remove redundant console logging for player disconnections and streamline control flow in `disconnectFromServer` method in `PlayerConnectionsHandler.cs`.
- Move dispatching of `PlayerLeaveEvent` to the next world update for consistency in `PlayerConnectionsHandler.cs`.
2025-09-25 15:37:17 -07:00
MSWS
e901d82153 feat: Refactor spawn logic; add LateSpawnListener
- Reorder `AddModBehavior` entries in `CS2ServiceCollection.cs` for improved readability and logical grouping, adding `BodySpawner`, `DamageCanceler`, and `LateSpawnListener` earlier in their sections and maintaining order consistency by moving various handlers.
- Remove duplicated entries and ensure all necessary handlers and listeners are included in `CS2ServiceCollection.cs`.
- Add new class `LateSpawnListener` in `Listeners/LateSpawnListener.cs` to handle player join events, implementing a respawn mechanism for new players joining when the game is not in progress.
- Remove game state condition and deferred respawn logic in `PlayerConnectionsHandler.cs`, changing player respawn behavior upon joining the server.
2025-09-25 15:28:24 -07:00
MSWS
f56106f125 Merge branch 'dev' of github.com:MSWS/TTT into dev 2025-09-25 15:23:09 -07:00
MSWS
57660e0957 Fix kill listener priority conflicting with round states (resolves #55) 2025-09-25 15:23:03 -07:00
MSWS
1ecef5767f Fix kill listener priority conflicting with round states (resolves 55) 2025-09-25 15:22:40 -07:00
MSWS
d1359b79c0 feat: Introduce shop module with event-driven updates (fixes #54)
```
Integrate New Features and Enhance Codebase

- Add a new project reference to `CS2.csproj` for integration with the Shop project.
- Introduce a new configuration class `CS2ShopConfig` to manage shop settings and player interactions.
- Implement new player event handling with `PlayerPurchaseItemEvent` and `PlayerBalanceEvent`, enabling cancellable item purchases and balance updates.
- Enhance the `ShopServiceCollection` with new behaviors for extended functionality, including `RoleAssignCreditor`, `BuyCommand`, and `BalanceCommand`.
- Improve `Shop.cs` by replacing `IPlayer` references with string identifiers, introducing event-driven balance updates, and enhancing messaging logic.
- Comprehensive changes across multiple utilities and configurations to support new team score management and event-driven architecture.
```
2025-09-25 15:02:58 -07:00
Isaac
216d5a9d5a Update issue templates (#50) 2025-09-25 13:43:52 -07:00
Isaac
5d2bead09c Update issue templates 2025-09-25 13:42:42 -07:00
MSWS
a0ce6aa53e Additional cleaning up and unit tests 2025-09-25 08:01:42 -07:00
MSWS
cb626d7cfa Fix README typo 2025-09-24 23:54:26 -07:00
MSWS
d83ac95245 Merge branch 'dev' of github.com:MSWS/TTT into dev 2025-09-24 23:49:04 -07:00
MSWS
8db9b3154d Update licenses 2025-09-24 23:48:58 -07:00
Isaac
3abe6153e3 Feat/karma (#48) 2025-09-24 23:47:59 -07:00
MSWS
fc25405a81 Reorganize CS2ServiceCollection 2025-09-24 23:38:40 -07:00
MSWS
da3a94f3b7 Fix TTT/Plugin README link 2025-09-24 23:34:49 -07:00
MSWS
4bf7b0cd13 Merge dev 2025-09-24 23:29:16 -07:00
MSWS
758d3fe13c refactor: Refactor and clean up event and listener logic
Refactor and Simplify Codebase with Improved Readability and Efficiency

- **OneShotDeagle.cs:**
  - Remove event-related dependencies and streamline class to focus on core functionality.

- **PlayerKillListener.cs:**
  - Simplify `OnKill` method, preparing for future enhancements, and clean up unused code.

- **IListener.cs and IEventBus.cs:**
  - Remove `IDisposable` dependency from `IListener`. Add obsolescence message for `RegisterListener` in `IEventBus`.

- **LogsCommand.cs and TTTCommand.cs:**
  - Consolidate logic for game checking and logging, enhancing error handling and readability.

- **RoundTimerListener.cs and CombatHandler.cs:**
  - Refactor event handlers for clear separation of responsibilities and process optimization.

- **Various CS2 Handlers and Commands:**
  - Streamline and modularize event handling and role management with newly introduced helper methods across handlers.
  - Refactor command logic for improved organization and maintenance.

- **Locale/StringLocalizer.cs and EventBus.cs:**
  - Refactor string handling and listener registration for enhanced clarity and performance.
2025-09-24 23:27:05 -07:00
MSWS
9045913074 feat: Implement role management via dependency injection
```
- Simplify and enhance `PlayerActionsLogger.cs` by using pattern matching for game status checks and improve logging calls with a `Provider` parameter.
- Update `DeathAction.cs` to support dependency injection and role management by modifying constructors and formatting methods.
- Add role management in `FakeAction.cs` by introducing `PlayerRole` and `OtherRole` properties.
- Mark `IsGameActive` in `IGameManager.cs` as obsolete to guide towards direct game state checks.
- Modify logging in `BodyIdentifyLogger.cs` to use a `Provider` parameter for better context.
- Improve role management in `IdentifyBodyAction.cs` with new properties and constructor overloads supporting dependency injection.
- Refactor `ActionTest.cs` to accommodate constructor changes in `FakeAction`, ensuring backward compatibility.
- Expand `IAction` interface with role properties and enhance `Format` method.
- Add footer text in `en.yml` and `GameMsgs.cs` for clearer game log outputs.
- Enhance `DamagedAction.cs` with dependency injection and role properties, improving role management.
- Adjust `CombatHandler.cs` to refine player event handling and platform checks.
- Clear up documentation comments in `StringLocalizer.cs`.
- Enhance `SimpleLogger.cs` with role management and improved log formatting.
- Deprecate `IsInProgress()` in `IGame` for more explicit game state checks.
```
2025-09-24 20:04:22 -07:00
MSWS
8748401b6b Basic shop balance giving 2025-09-24 17:06:01 -07:00
MSWS
7d5218914f Merge branch 'dev' into feat/karma 2025-09-24 16:26:45 -07:00
MSWS
137144a052 Reformat Raytrace: 2025-09-24 16:22:00 -07:00
MSWS
61d7f667ff Reformat and cleanup 2025-09-23 18:11:46 -07:00
MSWS
f53c00c4d8 Reformat and cleanup 2025-09-23 18:10:51 -07:00
MSWS
3f5a675af1 Fix unit tests 2025-09-23 18:08:26 -07:00
MSWS
48ec384b38 Fix unit tests 2025-09-23 18:07:21 -07:00
MSWS
2edee31419 Fix EventBus impl 2025-09-23 17:59:18 -07:00
MSWS
d4006e5750 Resolve merge conflicts 2025-09-23 17:57:33 -07:00
MSWS
a1a37452ef refactor: Refactor round end logic and enhance message style.
- Enhance message styling in `en.yml` by adding grey color to `TASER_SCANNED` translation.
- Align logical flow in `RoundTimerListener.cs` by moving the remaining time check in `OnRoundEnd`.
- Clean up `RoundTimerListener.cs` by removing commented-out code related to `EventRoundEnd`.
- Maintain role setting and team switching functionality in `RoundTimerListener.cs` within `OnRoundEnd`.
- Adjust winning team logic and event firing in `RoundTimerListener.cs` based on end reason.
- Ensure correct round transitions in `RoundTimerListener.cs` using scheduled timing logic.
2025-09-23 17:38:03 -07:00
MSWS
d9f002febe Fix body systems 2025-09-23 17:20:26 -07:00
MSWS
26cca670ee Add gamedata 2025-09-23 16:46:51 -07:00
MSWS
cafd050a85 Remove debugs 2025-09-23 16:39:22 -07:00
MSWS
a28c3aa0dd Overhaul raytracing 2025-09-23 13:04:40 -07:00
MSWS
2918a9965d Update raytrace sigs 2025-09-23 12:42:17 -07:00
MSWS
b57630b899 feat: Add taser scan message and role assignment logic
- Add a new translation entry for "TASER_SCANNED" in TTT/CS2/lang/en.yml, ensuring a dynamic message format.
- Enhance TTT/Game/Listeners/BaseListener.cs with dependencies for role assignment and message localization.
- Refactor TTT/Game/Events/Player/PlayerDamagedEvent.cs to improve attacker retrieval logic and robustness.
- Improve TTT/Game/lang/GameMsgs.cs by extracting role prefix determination into a separate method for clarity.
- Introduce new methods and directives in TTT/CS2/lang/CS2Msgs.cs for better integration with TTT API and improved message clarity.
- Update TTT/CS2/GameHandlers/DamageCancelers/TaserListenCanceler.cs to refine event handling logic with taser-specific enhancements.
2025-09-23 12:38:38 -07:00
MSWS
65c12696ed Debug compile on dev 2025-09-23 12:09:57 -07:00
MSWS
3206c30078 Debug 2025-09-23 12:04:04 -07:00
MSWS
f9f0c4e954 Fix failing tests 2025-09-16 21:33:01 -07:00
MSWS
45f492e44e Resolve initial merge conflicts 2025-09-16 21:30:34 -07:00
MSWS
c6f45276c3 refactor: Refactor damage handlers to use events +semver:minor
```
- Add OutOfRoundCanceler and TaserListenCanceler classes for improved damage cancellation in specific scenarios
- Mark RegisterListener method in IEventBus as obsolete
- Update ShopServiceCollection to remove generic type parameter from ShopCommand addition
- Change color representation for DetectiveRole in GameMsgs to DarkBlue
- Enhance ServiceCollectionExtensions with transient service registration and ICommand type handling
- Transition DamageCanceler to an event-driven architecture for improved flexibility
- Allow Player property in PlayerEvent to be set during initialization
- Register new damage cancelers in CS2ServiceCollection and simplify command service addition
- Refactor RoleIconsHandler to improve icon management and refine role assignments
- Update PlayerDamagedEvent for dynamic initialization and error handling
- Remove excessive "Respawning..." message from PlayerConnectionsHandler
- Narrow ShopCommand registration to only the "buy" subcommand
```
2025-09-16 21:20:51 -07:00
MSWS
9eef949501 refactor: Refactor module and listener loading logic
```
Refactor and enhance module management and logging across multiple components

- Update `TTT.cs` to differentiate between base and plugin modules during loading, improve logging for module operations, and revise initialization and activation of plugin modules.
- Enhance debugging and registration in `ServiceCollectionExtensions.cs` by adding diagnostic logs and ensuring proper registration of plugin modules and listeners with transient lifetimes.
- Remove redundant `Name` property from multiple logger and listener classes (`PlayerActionsLogger.cs`, `BodyIdentifyLogger.cs`, and `PlayerCausesEndListener.cs`), cleaning up unused code and simplifying logic for handling game-related events.
- Improve event dispatching efficiency in `EventBus.cs` by optimizing handler checks, and update DEBUG logging to handle nullability issues.
- Simplify `DamageCanceler.cs` by removing incorrect interface implementation and clarifying constructor and method usage.
```
2025-09-16 20:40:13 -07:00
MSWS
f1c6a784d1 refactor: Refactor codebase to remove Name and Version properties
Refactor Codebase for Simplification and Improved Modularization

- **RoundEndHandler.cs**
  - Removed `Name` and `Version` properties to simplify the class.
  - Maintained functionality for handling end-of-round events.

- **BaseListener.cs**
  - Removed `ITerrorModule` interface implementation and unnecessary properties.
  - Updated `Start` method to change listener lifecycle management.

- **CS2GameConfig.cs**
  - Simplified by removing `Name` and `Version` properties, focusing solely on game parameters.

- **GameServiceCollection.cs**
  - Changed listener addition method from `AddListener` to `AddModBehavior`, updated service registration terms.

- **DamageCanceler.cs**
  - Simplified class by removing `Name` and `Version` properties.
  - Enhanced damage processing with additional validity checks.

- Further updates include transitioning from `AddListener` to `AddModBehavior` across files, deprecating old registration methods in `EventBus.cs`, and comprehensive removal of `Name` and `Version` properties from various classes to streamline and refactor code structure. Additionally, obsolete methods were removed, and dependency injection patterns were adopted for intuitive system integration.
2025-09-16 19:53:21 -07:00
MSWS
112422e479 Add debug code to events 2025-09-11 18:01:40 -07:00
MSWS
6abdce7246 Merge branch 'dev' of github.com:MSWS/TTT into dev 2025-09-11 12:51:38 -07:00
MSWS
d3a021f40b Fix init loop 2025-09-11 12:51:27 -07:00
Isaac
f657599a0e Add core TTT shop system with commands and One-Shot Deagle item (#49) 2025-09-11 11:24:49 -07:00
Isaac
4d66afaec9 Update TTT/Test/Shop/Commands/BuyTest.cs
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
Signed-off-by: Isaac <git@msws.xyz>
2025-09-11 11:22:30 -07:00
Isaac
0667652ed4 Update TTT/Shop/Items/OneShotDeagle/DeagleDamageListener.cs
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
Signed-off-by: Isaac <git@msws.xyz>
2025-09-11 11:21:55 -07:00
MSWS
b41092fd69 feat: Refactor purchase logic and add BuyCommand tests
```plaintext
Implement comprehensive testing and enhance purchase logic

- Add `BuyTest` class to thoroughly test `BuyCommand` in the shop, covering various scenarios and ensuring correct game rule validation.
- Modify `OneShotDeagle`'s `CanPurchase` method to return a `PurchaseResult` enum for detailed purchasing results.
- Update `IShopItem` interface's `CanPurchase` method signature to use `PurchaseResult` for consistent result handling.
- Add `TestShopItem` class implementing the `IShopItem` interface, complete with properties, methods, and a successful `CanPurchase` implementation for testing.
- Improve `TestMessenger` with a null check for the player parameter and message logging for null player scenarios.
- Move `PurchaseResult.cs` to a new directory within the `Shop` folder for better organization.
- Refactor `CommandManagerTests` to use `ICommandManager` interface, ensuring interface-based testing without functional changes.
- Enhance `BuyCommand` with new aliases, asynchronous `Execute` method, and improved transaction logic, including balance checks and item search refactor.
```
2025-09-11 11:17:40 -07:00
MSWS
cc345ac010 Merge branch 'feat/karma' of github.com:MSWS/TTT into feat/karma 2025-09-09 15:24:29 -07:00
MSWS
fa1d732724 test: Refactor tests and cleanup PropMover code
- Await the `bus.Dispatch(deathEvent)` call in `OnKill_WithoutGame_DoesNothing` test.
- Remove unused import and eliminate the unused `IMessenger` component in `PropMover.cs`.
- Rename `refreshBodies` method to `refreshBody` for clarity in `PropMover.cs`.
- Refactor the iteration over `playersPressingE` to call the updated method in `PropMover.cs`.
- Enhance code readability in `PropMover.cs` through minor code style improvements, including removal of unnecessary exclamation points.
2025-09-09 15:24:23 -07:00
MSWS
4d5109b6be test: Additional unit tests regarding karma stacking 2025-09-09 15:24:23 -07:00
MSWS
00970f6789 feat: Refactor handlers and add KarmaSyncer feature
- Rename `RoundStartHandler` to `RoundStart_GameStartHandler` and update `Dispose()` method in `RoundStartHandler.cs`
- Rename `RoundEndHandler` to `RoundEnd_GameEndHandler` in `RoundEndHandler.cs`
- Update target framework to .NET 8.0 and add project reference to Karma project in `CS2.csproj`
- Update service collection for specific game start/end handlers and add plugin for player karma in `CS2ServiceCollection.cs`
- Introduce `KarmaSyncer` class for handling player karma with appropriate dependencies and event handling in `KarmaSyncer.cs`
2025-09-09 15:24:23 -07:00
MSWS
29d2e8a46c Format & Cleanup 2025-09-09 15:24:22 -07:00
MSWS
1d6526730a All unit tests passing 2025-09-09 15:24:22 -07:00
MSWS
98dc08c667 Overhaul event bus to support async listeners 2025-09-09 15:24:22 -07:00
MSWS
4a50d662af test: Refactor karma handling and enhance test coverage
```
- Remove `KarmaTest.cs`, eliminating a test case for default player karma verification upon creation.
- Introduce `KarmaListenerTests.cs` file, laying the groundwork for future KarmaListener test cases.
- Adjust `KeyedMemoryStorage.cs` to enable subclass access and method overriding by changing `data` dictionary to protected and marking `Load` and `Write` methods as virtual.
- Update `MemoryKarmaStorage.cs` with `Xunit.Internal` import, modify generic type parameter to `int`, refine code with target-typed `new()`, and override `Load` method with default karma value handling.
- Refactor `KarmaStorage.cs` to batch process karma updates asynchronously, simplify default karma handling, enhance error management, and refine karma caching.
```
2025-09-09 15:24:22 -07:00
MSWS
45727da462 Start work on adding unit testing 2025-09-09 15:24:22 -07:00
MSWS
fc2104e71a feat: Introduce Karma module with DI and refactoring
```
- Add `KarmaServiceCollection` for dependency injection setup, facilitating the registration of `IKarmaService` with scoped lifetime.
- Update `TTTServiceCollection` to include new services for Karma management and necessary game services.
- Refactor `KarmaStorage` to implement `IKarmaService`, simplifying interface responsibilities and removing previous interface implementations.
- Configure `Plugin.csproj` with .NET 8.0, implicit usings, nullable reference types, and setup publish output handling.
- Introduce `IKarmaService` interface to streamline access and interaction with karma functionalities.
- Create `KarmaListener` class for managing karma adjustments during game events, implementing event handling and asynchronous tasks.
```
2025-09-09 15:24:22 -07:00
MSWS
375108dd85 Remove unnecessary null check 2025-09-09 15:24:22 -07:00
MSWS
aded3fb6a2 feat: Introduce Karma management system
- Create a new KarmaStorage class to handle player karma with MySQL and caching
- Add the Karma project file with .NET 8.0 target and necessary references
- Include the Karma project in TTT.sln with Debug and Release configurations
- Define a Karma configuration file with database and karma settings
- Introduce a KarmaUpdateEvent class for managing player karma updates with event cancellation support
2025-09-09 15:24:22 -07:00
MSWS
519578dcd9 Merge branch 'feat/shop' of github.com:MSWS/TTT into feat/shop 2025-09-09 15:24:10 -07:00
MSWS
2ebc25a692 refactor: Add Skip method across command classes
- Add a `Skip` method to `CS2CommandInfo` for argument skipping
- Rename `sub` to `subcommands` in `ShopCommand` for clarity and update execution logic
- Make `caller` parameter nullable in `TestCommandInfo` and introduce `Skip` method for better argument handling
- Add `Skip` method to `ICommandInfo` interface for consistent argument skipping functionality
2025-09-09 15:24:03 -07:00
MSWS
1810bd1473 feat: Add shop buy command 2025-09-09 15:24:03 -07:00
MSWS
8ea14e7960 Register services 2025-09-09 15:24:03 -07:00
MSWS
3dc3cd08f4 Manually copy over old work of shop command 2025-09-09 15:24:03 -07:00
MSWS
78e0b64bb3 refactor: Move classes into proper dirs 2025-09-09 15:24:03 -07:00
MSWS
5977d87216 Remove unused test 2025-09-09 15:23:53 -07:00
MSWS
8cdb19f23c refactor: Add Skip method across command classes
- Add a `Skip` method to `CS2CommandInfo` for argument skipping
- Rename `sub` to `subcommands` in `ShopCommand` for clarity and update execution logic
- Make `caller` parameter nullable in `TestCommandInfo` and introduce `Skip` method for better argument handling
- Add `Skip` method to `ICommandInfo` interface for consistent argument skipping functionality
2025-09-09 15:21:08 -07:00
MSWS
a44b5b00a2 feat: Add shop buy command 2025-09-09 14:56:31 -07:00
MSWS
352de1f667 Register services 2025-09-09 11:31:35 -07:00
MSWS
1b8d201567 Manually copy over old work of shop command 2025-09-09 11:28:40 -07:00
MSWS
f753cb01c4 refactor: Move classes into proper dirs 2025-09-09 11:26:08 -07:00
MSWS
529af8c776 test: Refactor tests and cleanup PropMover code
- Await the `bus.Dispatch(deathEvent)` call in `OnKill_WithoutGame_DoesNothing` test.
- Remove unused import and eliminate the unused `IMessenger` component in `PropMover.cs`.
- Rename `refreshBodies` method to `refreshBody` for clarity in `PropMover.cs`.
- Refactor the iteration over `playersPressingE` to call the updated method in `PropMover.cs`.
- Enhance code readability in `PropMover.cs` through minor code style improvements, including removal of unnecessary exclamation points.
2025-09-09 11:07:15 -07:00
MSWS
6016f62931 test: Additional unit tests regarding karma stacking 2025-09-09 11:02:30 -07:00
MSWS
50f5a835de feat: Refactor handlers and add KarmaSyncer feature
- Rename `RoundStartHandler` to `RoundStart_GameStartHandler` and update `Dispose()` method in `RoundStartHandler.cs`
- Rename `RoundEndHandler` to `RoundEnd_GameEndHandler` in `RoundEndHandler.cs`
- Update target framework to .NET 8.0 and add project reference to Karma project in `CS2.csproj`
- Update service collection for specific game start/end handlers and add plugin for player karma in `CS2ServiceCollection.cs`
- Introduce `KarmaSyncer` class for handling player karma with appropriate dependencies and event handling in `KarmaSyncer.cs`
2025-09-09 10:47:59 -07:00
MSWS
46104f142f Format & Cleanup 2025-09-09 10:37:47 -07:00
MSWS
6b7d89dbf0 All unit tests passing 2025-09-09 10:32:02 -07:00
Isaac
332b6e6501 build(deps): Bump actions/setup-dotnet from 4 to 5 (#46)
Bumps [actions/setup-dotnet](https://github.com/actions/setup-dotnet)
from 4 to 5.
<details>
<summary>Release notes</summary>
<p><em>Sourced from <a
href="https://github.com/actions/setup-dotnet/releases">actions/setup-dotnet's
releases</a>.</em></p>
<blockquote>
<h2>v5.0.0</h2>
<h2>What's Changed</h2>
<h3>Breaking Changes</h3>
<ul>
<li>Upgrade to Node.js 24 and modernize async usage by <a
href="https://github.com/salmanmkc"><code>@​salmanmkc</code></a> in <a
href="https://redirect.github.com/actions/setup-dotnet/pull/654">actions/setup-dotnet#654</a></li>
</ul>
<p>Make sure your runner is updated to this version or newer to use this
release. v2.327.1 <a
href="https://github.com/actions/runner/releases/tag/v2.327.1">Release
Notes</a></p>
<h3>Dependency Updates</h3>
<ul>
<li>Upgrade <code>@​action/cache</code> from 4.0.2 to 4.0.3 by <a
href="https://github.com/aparnajyothi-y"><code>@​aparnajyothi-y</code></a>
in <a
href="https://redirect.github.com/actions/setup-dotnet/pull/622">actions/setup-dotnet#622</a></li>
<li>Upgrade husky from 8.0.3 to 9.1.7 by <a
href="https://github.com/dependabot"><code>@​dependabot</code></a>[bot]
in <a
href="https://redirect.github.com/actions/setup-dotnet/pull/591">actions/setup-dotnet#591</a></li>
<li>Upgrade <code>@​actions/glob</code> from 0.4.0 to 0.5.0 by <a
href="https://github.com/dependabot"><code>@​dependabot</code></a>[bot]
in <a
href="https://redirect.github.com/actions/setup-dotnet/pull/594">actions/setup-dotnet#594</a></li>
<li>Upgrade eslint-config-prettier from 9.1.0 to 10.1.5 by <a
href="https://github.com/dependabot"><code>@​dependabot</code></a>[bot]
in <a
href="https://redirect.github.com/actions/setup-dotnet/pull/639">actions/setup-dotnet#639</a></li>
<li>Upgrade undici from 5.28.5 to 5.29.0 by <a
href="https://github.com/dependabot"><code>@​dependabot</code></a>[bot]
in <a
href="https://redirect.github.com/actions/setup-dotnet/pull/641">actions/setup-dotnet#641</a></li>
<li>Upgrade form-data to bring in fix for critical vulnerability by <a
href="https://github.com/gowridurgad"><code>@​gowridurgad</code></a> in
<a
href="https://redirect.github.com/actions/setup-dotnet/pull/652">actions/setup-dotnet#652</a></li>
<li>Upgrade actions/checkout from 4 to 5 by <a
href="https://github.com/dependabot"><code>@​dependabot</code></a>[bot]
in <a
href="https://redirect.github.com/actions/setup-dotnet/pull/662">actions/setup-dotnet#662</a></li>
</ul>
<h3>Bug Fixes</h3>
<ul>
<li>Remove Support for older .NET Versions and Update installers scripts
by <a
href="https://github.com/gowridurgad"><code>@​gowridurgad</code></a> in
<a
href="https://redirect.github.com/actions/setup-dotnet/pull/647">actions/setup-dotnet#647</a></li>
</ul>
<h2>New Contributors</h2>
<ul>
<li><a
href="https://github.com/gowridurgad"><code>@​gowridurgad</code></a>
made their first contribution in <a
href="https://redirect.github.com/actions/setup-dotnet/pull/647">actions/setup-dotnet#647</a></li>
<li><a href="https://github.com/salmanmkc"><code>@​salmanmkc</code></a>
made their first contribution in <a
href="https://redirect.github.com/actions/setup-dotnet/pull/654">actions/setup-dotnet#654</a></li>
</ul>
<p><strong>Full Changelog</strong>: <a
href="https://github.com/actions/setup-dotnet/compare/v4...v5.0.0">https://github.com/actions/setup-dotnet/compare/v4...v5.0.0</a></p>
<h2>v4.3.1</h2>
<h2>What's Changed</h2>
<ul>
<li><code>v4</code> - Remove <code>azureedge.net</code> fallback logic
and update install scripts by <a
href="https://github.com/zaataylor"><code>@​zaataylor</code></a> in <a
href="https://redirect.github.com/actions/setup-dotnet/pull/572">actions/setup-dotnet#572</a>
As outlined in<a
href="https://devblogs.microsoft.com/dotnet/critical-dotnet-install-links-are-changing/#call-to-action">
Critical .NET Install Links Are Changing</a>, remove the storage account
fallback logic added for v4 in <a
href="https://redirect.github.com/actions/setup-dotnet/pull/566">actions/setup-dotnet#566</a>
and update the install scripts accordingly.
<strong>Related issue</strong>: <a
href="https://redirect.github.com/dotnet/install-scripts/issues/559">dotnet/install-scripts#559</a></li>
<li>upgrade <code>@​actions/cache</code> to 4.0.2 by <a
href="https://github.com/HarithaVattikuti"><code>@​HarithaVattikuti</code></a>
in <a
href="https://redirect.github.com/actions/setup-dotnet/pull/615">actions/setup-dotnet#615</a></li>
</ul>
<p><strong>Full Changelog</strong>: <a
href="https://github.com/actions/setup-dotnet/compare/v4...v4.3.1">https://github.com/actions/setup-dotnet/compare/v4...v4.3.1</a></p>
<h2>v4.3.0</h2>
<h2>What's Changed</h2>
<ul>
<li>README update - add permissions section by <a
href="https://github.com/benwells"><code>@​benwells</code></a> in <a
href="https://redirect.github.com/actions/setup-dotnet/pull/587">actions/setup-dotnet#587</a></li>
<li>Configure Dependabot settings by <a
href="https://github.com/HarithaVattikuti"><code>@​HarithaVattikuti</code></a>
in <a
href="https://redirect.github.com/actions/setup-dotnet/pull/585">actions/setup-dotnet#585</a></li>
<li>Upgrade <strong>cache</strong> from 3.2.4 to 4.0.0 by <a
href="https://github.com/aparnajyothi-y"><code>@​aparnajyothi-y</code></a>
in <a
href="https://redirect.github.com/actions/setup-dotnet/pull/586">actions/setup-dotnet#586</a></li>
<li>Upgrade <strong>actions/publish-immutable-action</strong> from 0.0.3
to 0.0.4 by <a
href="https://github.com/dependabot"><code>@​dependabot</code></a> in <a
href="https://redirect.github.com/actions/setup-dotnet/pull/590">actions/setup-dotnet#590</a></li>
<li>Upgrade <strong><code>@​actions/http-client</code></strong> from
2.2.1 to 2.2.3 by <a
href="https://github.com/dependabot"><code>@​dependabot</code></a> in <a
href="https://redirect.github.com/actions/setup-dotnet/pull/592">actions/setup-dotnet#592</a></li>
<li>Upgrade <strong>undici</strong> from 5.28.4 to 5.28.5 by <a
href="https://github.com/dependabot"><code>@​dependabot</code></a> in <a
href="https://redirect.github.com/actions/setup-dotnet/pull/596">actions/setup-dotnet#596</a></li>
</ul>
<h2>New Contributors</h2>
<ul>
<li><a href="https://github.com/benwells"><code>@​benwells</code></a>
made their first contribution in <a
href="https://redirect.github.com/actions/setup-dotnet/pull/587">actions/setup-dotnet#587</a></li>
<li><a
href="https://github.com/aparnajyothi-y"><code>@​aparnajyothi-y</code></a>
made their first contribution in <a
href="https://redirect.github.com/actions/setup-dotnet/pull/586">actions/setup-dotnet#586</a></li>
</ul>
<!-- raw HTML omitted -->
</blockquote>
<p>... (truncated)</p>
</details>
<details>
<summary>Commits</summary>
<ul>
<li><a
href="d4c94342e5"><code>d4c9434</code></a>
Update to Node.js 24 and modernize async usage (<a
href="https://redirect.github.com/actions/setup-dotnet/issues/654">#654</a>)</li>
<li><a
href="5c125af7da"><code>5c125af</code></a>
Bump actions/checkout from 4 to 5 (<a
href="https://redirect.github.com/actions/setup-dotnet/issues/662">#662</a>)</li>
<li><a
href="87c6e11776"><code>87c6e11</code></a>
Bumps form-data (<a
href="https://redirect.github.com/actions/setup-dotnet/issues/652">#652</a>)</li>
<li><a
href="06a5327ecf"><code>06a5327</code></a>
Bump undici from 5.28.5 to 5.29.0 (<a
href="https://redirect.github.com/actions/setup-dotnet/issues/641">#641</a>)</li>
<li><a
href="e8e5b8203e"><code>e8e5b82</code></a>
Bump eslint-config-prettier from 9.1.0 to 10.1.5 (<a
href="https://redirect.github.com/actions/setup-dotnet/issues/639">#639</a>)</li>
<li><a
href="bf4cd79173"><code>bf4cd79</code></a>
Bump <code>@​actions/glob</code> from 0.4.0 to 0.5.0 (<a
href="https://redirect.github.com/actions/setup-dotnet/issues/594">#594</a>)</li>
<li><a
href="4ddad1c881"><code>4ddad1c</code></a>
Bump husky from 8.0.3 to 9.1.7 (<a
href="https://redirect.github.com/actions/setup-dotnet/issues/591">#591</a>)</li>
<li><a
href="0f55b457d2"><code>0f55b45</code></a>
removes end-of-line dotnet versions (<a
href="https://redirect.github.com/actions/setup-dotnet/issues/647">#647</a>)</li>
<li><a
href="267870a9c4"><code>267870a</code></a>
upgrade actions/cache to 4.0.3 (<a
href="https://redirect.github.com/actions/setup-dotnet/issues/622">#622</a>)</li>
<li>See full diff in <a
href="https://github.com/actions/setup-dotnet/compare/v4...v5">compare
view</a></li>
</ul>
</details>
<br />


[![Dependabot compatibility
score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=actions/setup-dotnet&package-manager=github_actions&previous-version=4&new-version=5)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores)

Dependabot will resolve any conflicts with this PR as long as you don't
alter it yourself. You can also trigger a rebase manually by commenting
`@dependabot rebase`.

[//]: # (dependabot-automerge-start)
[//]: # (dependabot-automerge-end)

---

<details>
<summary>Dependabot commands and options</summary>
<br />

You can trigger Dependabot actions by commenting on this PR:
- `@dependabot rebase` will rebase this PR
- `@dependabot recreate` will recreate this PR, overwriting any edits
that have been made to it
- `@dependabot merge` will merge this PR after your CI passes on it
- `@dependabot squash and merge` will squash and merge this PR after
your CI passes on it
- `@dependabot cancel merge` will cancel a previously requested merge
and block automerging
- `@dependabot reopen` will reopen this PR if it is closed
- `@dependabot close` will close this PR and stop Dependabot recreating
it. You can achieve the same result by closing it manually
- `@dependabot show <dependency name> ignore conditions` will show all
of the ignore conditions of the specified dependency
- `@dependabot ignore this major version` will close this PR and stop
Dependabot creating any more for this major version (unless you reopen
the PR or upgrade to it yourself)
- `@dependabot ignore this minor version` will close this PR and stop
Dependabot creating any more for this minor version (unless you reopen
the PR or upgrade to it yourself)
- `@dependabot ignore this dependency` will close this PR and stop
Dependabot creating any more for this dependency (unless you reopen the
PR or upgrade to it yourself)


</details>
2025-09-09 09:08:32 -07:00
MSWS
8c385934b3 Overhaul event bus to support async listeners 2025-09-09 09:04:54 -07:00
MSWS
04f79551f7 test: Refactor karma handling and enhance test coverage
```
- Remove `KarmaTest.cs`, eliminating a test case for default player karma verification upon creation.
- Introduce `KarmaListenerTests.cs` file, laying the groundwork for future KarmaListener test cases.
- Adjust `KeyedMemoryStorage.cs` to enable subclass access and method overriding by changing `data` dictionary to protected and marking `Load` and `Write` methods as virtual.
- Update `MemoryKarmaStorage.cs` with `Xunit.Internal` import, modify generic type parameter to `int`, refine code with target-typed `new()`, and override `Load` method with default karma value handling.
- Refactor `KarmaStorage.cs` to batch process karma updates asynchronously, simplify default karma handling, enhance error management, and refine karma caching.
```
2025-09-09 08:19:56 -07:00
MSWS
b08f9234ff Start work on adding unit testing 2025-09-08 21:22:36 -07:00
MSWS
87b83edb55 feat: Introduce Karma module with DI and refactoring
```
- Add `KarmaServiceCollection` for dependency injection setup, facilitating the registration of `IKarmaService` with scoped lifetime.
- Update `TTTServiceCollection` to include new services for Karma management and necessary game services.
- Refactor `KarmaStorage` to implement `IKarmaService`, simplifying interface responsibilities and removing previous interface implementations.
- Configure `Plugin.csproj` with .NET 8.0, implicit usings, nullable reference types, and setup publish output handling.
- Introduce `IKarmaService` interface to streamline access and interaction with karma functionalities.
- Create `KarmaListener` class for managing karma adjustments during game events, implementing event handling and asynchronous tasks.
```
2025-09-08 20:42:02 -07:00
dependabot[bot]
de7639d986 build(deps): Bump actions/setup-dotnet from 4 to 5
Bumps [actions/setup-dotnet](https://github.com/actions/setup-dotnet) from 4 to 5.
- [Release notes](https://github.com/actions/setup-dotnet/releases)
- [Commits](https://github.com/actions/setup-dotnet/compare/v4...v5)

---
updated-dependencies:
- dependency-name: actions/setup-dotnet
  dependency-version: '5'
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-09-08 00:34:50 +00:00
MSWS
a90e33b69d Remove unnecessary null check 2025-08-19 03:10:58 -07:00
MSWS
700074b130 feat: Introduce Karma management system
- Create a new KarmaStorage class to handle player karma with MySQL and caching
- Add the Karma project file with .NET 8.0 target and necessary references
- Include the Karma project in TTT.sln with Debug and Release configurations
- Define a Karma configuration file with database and karma settings
- Introduce a KarmaUpdateEvent class for managing player karma updates with event cancellation support
2025-08-19 03:09:59 -07:00
Isaac
6c06071d8a PlayerPawn -> Pawn, added DamageCanceler 2025-08-19 02:14:04 -07:00
MSWS
d89c70c41e Fix compilation error 2025-08-19 02:10:19 -07:00
Isaac
58012cb112 Update TTT/Game/Actions/DamagedAction.cs
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
Signed-off-by: Isaac <git@msws.xyz>
2025-08-19 02:08:16 -07:00
Isaac
febf34fcda build(deps): Bump actions/checkout from 4 to 5 (#44)
Bumps [actions/checkout](https://github.com/actions/checkout) from 4 to
5.
<details>
<summary>Release notes</summary>
<p><em>Sourced from <a
href="https://github.com/actions/checkout/releases">actions/checkout's
releases</a>.</em></p>
<blockquote>
<h2>v5.0.0</h2>
<h2>What's Changed</h2>
<ul>
<li>Update actions checkout to use node 24 by <a
href="https://github.com/salmanmkc"><code>@​salmanmkc</code></a> in <a
href="https://redirect.github.com/actions/checkout/pull/2226">actions/checkout#2226</a></li>
<li>Prepare v5.0.0 release by <a
href="https://github.com/salmanmkc"><code>@​salmanmkc</code></a> in <a
href="https://redirect.github.com/actions/checkout/pull/2238">actions/checkout#2238</a></li>
</ul>
<h2>⚠️ Minimum Compatible Runner Version</h2>
<p><strong>v2.327.1</strong><br />
<a
href="https://github.com/actions/runner/releases/tag/v2.327.1">Release
Notes</a></p>
<p>Make sure your runner is updated to this version or newer to use this
release.</p>
<p><strong>Full Changelog</strong>: <a
href="https://github.com/actions/checkout/compare/v4...v5.0.0">https://github.com/actions/checkout/compare/v4...v5.0.0</a></p>
<h2>v4.3.0</h2>
<h2>What's Changed</h2>
<ul>
<li>docs: update README.md by <a
href="https://github.com/motss"><code>@​motss</code></a> in <a
href="https://redirect.github.com/actions/checkout/pull/1971">actions/checkout#1971</a></li>
<li>Add internal repos for checking out multiple repositories by <a
href="https://github.com/mouismail"><code>@​mouismail</code></a> in <a
href="https://redirect.github.com/actions/checkout/pull/1977">actions/checkout#1977</a></li>
<li>Documentation update - add recommended permissions to Readme by <a
href="https://github.com/benwells"><code>@​benwells</code></a> in <a
href="https://redirect.github.com/actions/checkout/pull/2043">actions/checkout#2043</a></li>
<li>Adjust positioning of user email note and permissions heading by <a
href="https://github.com/joshmgross"><code>@​joshmgross</code></a> in <a
href="https://redirect.github.com/actions/checkout/pull/2044">actions/checkout#2044</a></li>
<li>Update README.md by <a
href="https://github.com/nebuk89"><code>@​nebuk89</code></a> in <a
href="https://redirect.github.com/actions/checkout/pull/2194">actions/checkout#2194</a></li>
<li>Update CODEOWNERS for actions by <a
href="https://github.com/TingluoHuang"><code>@​TingluoHuang</code></a>
in <a
href="https://redirect.github.com/actions/checkout/pull/2224">actions/checkout#2224</a></li>
<li>Update package dependencies by <a
href="https://github.com/salmanmkc"><code>@​salmanmkc</code></a> in <a
href="https://redirect.github.com/actions/checkout/pull/2236">actions/checkout#2236</a></li>
<li>Prepare release v4.3.0 by <a
href="https://github.com/salmanmkc"><code>@​salmanmkc</code></a> in <a
href="https://redirect.github.com/actions/checkout/pull/2237">actions/checkout#2237</a></li>
</ul>
<h2>New Contributors</h2>
<ul>
<li><a href="https://github.com/motss"><code>@​motss</code></a> made
their first contribution in <a
href="https://redirect.github.com/actions/checkout/pull/1971">actions/checkout#1971</a></li>
<li><a href="https://github.com/mouismail"><code>@​mouismail</code></a>
made their first contribution in <a
href="https://redirect.github.com/actions/checkout/pull/1977">actions/checkout#1977</a></li>
<li><a href="https://github.com/benwells"><code>@​benwells</code></a>
made their first contribution in <a
href="https://redirect.github.com/actions/checkout/pull/2043">actions/checkout#2043</a></li>
<li><a href="https://github.com/nebuk89"><code>@​nebuk89</code></a> made
their first contribution in <a
href="https://redirect.github.com/actions/checkout/pull/2194">actions/checkout#2194</a></li>
<li><a href="https://github.com/salmanmkc"><code>@​salmanmkc</code></a>
made their first contribution in <a
href="https://redirect.github.com/actions/checkout/pull/2236">actions/checkout#2236</a></li>
</ul>
<p><strong>Full Changelog</strong>: <a
href="https://github.com/actions/checkout/compare/v4...v4.3.0">https://github.com/actions/checkout/compare/v4...v4.3.0</a></p>
<h2>v4.2.2</h2>
<h2>What's Changed</h2>
<ul>
<li><code>url-helper.ts</code> now leverages well-known environment
variables by <a href="https://github.com/jww3"><code>@​jww3</code></a>
in <a
href="https://redirect.github.com/actions/checkout/pull/1941">actions/checkout#1941</a></li>
<li>Expand unit test coverage for <code>isGhes</code> by <a
href="https://github.com/jww3"><code>@​jww3</code></a> in <a
href="https://redirect.github.com/actions/checkout/pull/1946">actions/checkout#1946</a></li>
</ul>
<p><strong>Full Changelog</strong>: <a
href="https://github.com/actions/checkout/compare/v4.2.1...v4.2.2">https://github.com/actions/checkout/compare/v4.2.1...v4.2.2</a></p>
<h2>v4.2.1</h2>
<h2>What's Changed</h2>
<ul>
<li>Check out other refs/* by commit if provided, fall back to ref by <a
href="https://github.com/orhantoy"><code>@​orhantoy</code></a> in <a
href="https://redirect.github.com/actions/checkout/pull/1924">actions/checkout#1924</a></li>
</ul>
<h2>New Contributors</h2>
<ul>
<li><a href="https://github.com/Jcambass"><code>@​Jcambass</code></a>
made their first contribution in <a
href="https://redirect.github.com/actions/checkout/pull/1919">actions/checkout#1919</a></li>
</ul>
<p><strong>Full Changelog</strong>: <a
href="https://github.com/actions/checkout/compare/v4.2.0...v4.2.1">https://github.com/actions/checkout/compare/v4.2.0...v4.2.1</a></p>
<!-- raw HTML omitted -->
</blockquote>
<p>... (truncated)</p>
</details>
<details>
<summary>Changelog</summary>
<p><em>Sourced from <a
href="https://github.com/actions/checkout/blob/main/CHANGELOG.md">actions/checkout's
changelog</a>.</em></p>
<blockquote>
<h1>Changelog</h1>
<h2>V5.0.0</h2>
<ul>
<li>Update actions checkout to use node 24 by <a
href="https://github.com/salmanmkc"><code>@​salmanmkc</code></a> in <a
href="https://redirect.github.com/actions/checkout/pull/2226">actions/checkout#2226</a></li>
</ul>
<h2>V4.3.0</h2>
<ul>
<li>docs: update README.md by <a
href="https://github.com/motss"><code>@​motss</code></a> in <a
href="https://redirect.github.com/actions/checkout/pull/1971">actions/checkout#1971</a></li>
<li>Add internal repos for checking out multiple repositories by <a
href="https://github.com/mouismail"><code>@​mouismail</code></a> in <a
href="https://redirect.github.com/actions/checkout/pull/1977">actions/checkout#1977</a></li>
<li>Documentation update - add recommended permissions to Readme by <a
href="https://github.com/benwells"><code>@​benwells</code></a> in <a
href="https://redirect.github.com/actions/checkout/pull/2043">actions/checkout#2043</a></li>
<li>Adjust positioning of user email note and permissions heading by <a
href="https://github.com/joshmgross"><code>@​joshmgross</code></a> in <a
href="https://redirect.github.com/actions/checkout/pull/2044">actions/checkout#2044</a></li>
<li>Update README.md by <a
href="https://github.com/nebuk89"><code>@​nebuk89</code></a> in <a
href="https://redirect.github.com/actions/checkout/pull/2194">actions/checkout#2194</a></li>
<li>Update CODEOWNERS for actions by <a
href="https://github.com/TingluoHuang"><code>@​TingluoHuang</code></a>
in <a
href="https://redirect.github.com/actions/checkout/pull/2224">actions/checkout#2224</a></li>
<li>Update package dependencies by <a
href="https://github.com/salmanmkc"><code>@​salmanmkc</code></a> in <a
href="https://redirect.github.com/actions/checkout/pull/2236">actions/checkout#2236</a></li>
</ul>
<h2>v4.2.2</h2>
<ul>
<li><code>url-helper.ts</code> now leverages well-known environment
variables by <a href="https://github.com/jww3"><code>@​jww3</code></a>
in <a
href="https://redirect.github.com/actions/checkout/pull/1941">actions/checkout#1941</a></li>
<li>Expand unit test coverage for <code>isGhes</code> by <a
href="https://github.com/jww3"><code>@​jww3</code></a> in <a
href="https://redirect.github.com/actions/checkout/pull/1946">actions/checkout#1946</a></li>
</ul>
<h2>v4.2.1</h2>
<ul>
<li>Check out other refs/* by commit if provided, fall back to ref by <a
href="https://github.com/orhantoy"><code>@​orhantoy</code></a> in <a
href="https://redirect.github.com/actions/checkout/pull/1924">actions/checkout#1924</a></li>
</ul>
<h2>v4.2.0</h2>
<ul>
<li>Add Ref and Commit outputs by <a
href="https://github.com/lucacome"><code>@​lucacome</code></a> in <a
href="https://redirect.github.com/actions/checkout/pull/1180">actions/checkout#1180</a></li>
<li>Dependency updates by <a
href="https://github.com/dependabot"><code>@​dependabot</code></a>- <a
href="https://redirect.github.com/actions/checkout/pull/1777">actions/checkout#1777</a>,
<a
href="https://redirect.github.com/actions/checkout/pull/1872">actions/checkout#1872</a></li>
</ul>
<h2>v4.1.7</h2>
<ul>
<li>Bump the minor-npm-dependencies group across 1 directory with 4
updates by <a
href="https://github.com/dependabot"><code>@​dependabot</code></a> in <a
href="https://redirect.github.com/actions/checkout/pull/1739">actions/checkout#1739</a></li>
<li>Bump actions/checkout from 3 to 4 by <a
href="https://github.com/dependabot"><code>@​dependabot</code></a> in <a
href="https://redirect.github.com/actions/checkout/pull/1697">actions/checkout#1697</a></li>
<li>Check out other refs/* by commit by <a
href="https://github.com/orhantoy"><code>@​orhantoy</code></a> in <a
href="https://redirect.github.com/actions/checkout/pull/1774">actions/checkout#1774</a></li>
<li>Pin actions/checkout's own workflows to a known, good, stable
version. by <a href="https://github.com/jww3"><code>@​jww3</code></a> in
<a
href="https://redirect.github.com/actions/checkout/pull/1776">actions/checkout#1776</a></li>
</ul>
<h2>v4.1.6</h2>
<ul>
<li>Check platform to set archive extension appropriately by <a
href="https://github.com/cory-miller"><code>@​cory-miller</code></a> in
<a
href="https://redirect.github.com/actions/checkout/pull/1732">actions/checkout#1732</a></li>
</ul>
<h2>v4.1.5</h2>
<ul>
<li>Update NPM dependencies by <a
href="https://github.com/cory-miller"><code>@​cory-miller</code></a> in
<a
href="https://redirect.github.com/actions/checkout/pull/1703">actions/checkout#1703</a></li>
<li>Bump github/codeql-action from 2 to 3 by <a
href="https://github.com/dependabot"><code>@​dependabot</code></a> in <a
href="https://redirect.github.com/actions/checkout/pull/1694">actions/checkout#1694</a></li>
<li>Bump actions/setup-node from 1 to 4 by <a
href="https://github.com/dependabot"><code>@​dependabot</code></a> in <a
href="https://redirect.github.com/actions/checkout/pull/1696">actions/checkout#1696</a></li>
<li>Bump actions/upload-artifact from 2 to 4 by <a
href="https://github.com/dependabot"><code>@​dependabot</code></a> in <a
href="https://redirect.github.com/actions/checkout/pull/1695">actions/checkout#1695</a></li>
<li>README: Suggest <code>user.email</code> to be
<code>41898282+github-actions[bot]@users.noreply.github.com</code> by <a
href="https://github.com/cory-miller"><code>@​cory-miller</code></a> in
<a
href="https://redirect.github.com/actions/checkout/pull/1707">actions/checkout#1707</a></li>
</ul>
<h2>v4.1.4</h2>
<ul>
<li>Disable <code>extensions.worktreeConfig</code> when disabling
<code>sparse-checkout</code> by <a
href="https://github.com/jww3"><code>@​jww3</code></a> in <a
href="https://redirect.github.com/actions/checkout/pull/1692">actions/checkout#1692</a></li>
<li>Add dependabot config by <a
href="https://github.com/cory-miller"><code>@​cory-miller</code></a> in
<a
href="https://redirect.github.com/actions/checkout/pull/1688">actions/checkout#1688</a></li>
<li>Bump the minor-actions-dependencies group with 2 updates by <a
href="https://github.com/dependabot"><code>@​dependabot</code></a> in <a
href="https://redirect.github.com/actions/checkout/pull/1693">actions/checkout#1693</a></li>
<li>Bump word-wrap from 1.2.3 to 1.2.5 by <a
href="https://github.com/dependabot"><code>@​dependabot</code></a> in <a
href="https://redirect.github.com/actions/checkout/pull/1643">actions/checkout#1643</a></li>
</ul>
<h2>v4.1.3</h2>
<!-- raw HTML omitted -->
</blockquote>
<p>... (truncated)</p>
</details>
<details>
<summary>Commits</summary>
<ul>
<li><a
href="08c6903cd8"><code>08c6903</code></a>
Prepare v5.0.0 release (<a
href="https://redirect.github.com/actions/checkout/issues/2238">#2238</a>)</li>
<li><a
href="9f265659d3"><code>9f26565</code></a>
Update actions checkout to use node 24 (<a
href="https://redirect.github.com/actions/checkout/issues/2226">#2226</a>)</li>
<li>See full diff in <a
href="https://github.com/actions/checkout/compare/v4...v5">compare
view</a></li>
</ul>
</details>
<br />


[![Dependabot compatibility
score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=actions/checkout&package-manager=github_actions&previous-version=4&new-version=5)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores)

Dependabot will resolve any conflicts with this PR as long as you don't
alter it yourself. You can also trigger a rebase manually by commenting
`@dependabot rebase`.

[//]: # (dependabot-automerge-start)
[//]: # (dependabot-automerge-end)

---

<details>
<summary>Dependabot commands and options</summary>
<br />

You can trigger Dependabot actions by commenting on this PR:
- `@dependabot rebase` will rebase this PR
- `@dependabot recreate` will recreate this PR, overwriting any edits
that have been made to it
- `@dependabot merge` will merge this PR after your CI passes on it
- `@dependabot squash and merge` will squash and merge this PR after
your CI passes on it
- `@dependabot cancel merge` will cancel a previously requested merge
and block automerging
- `@dependabot reopen` will reopen this PR if it is closed
- `@dependabot close` will close this PR and stop Dependabot recreating
it. You can achieve the same result by closing it manually
- `@dependabot show <dependency name> ignore conditions` will show all
of the ignore conditions of the specified dependency
- `@dependabot ignore this major version` will close this PR and stop
Dependabot creating any more for this major version (unless you reopen
the PR or upgrade to it yourself)
- `@dependabot ignore this minor version` will close this PR and stop
Dependabot creating any more for this minor version (unless you reopen
the PR or upgrade to it yourself)
- `@dependabot ignore this dependency` will close this PR and stop
Dependabot creating any more for this dependency (unless you reopen the
PR or upgrade to it yourself)


</details>
2025-08-19 02:05:21 -07:00
Isaac
44dafdd606 build(deps): Bump softprops/action-gh-release from 1 to 2 (#45)
Bumps
[softprops/action-gh-release](https://github.com/softprops/action-gh-release)
from 1 to 2.
<details>
<summary>Release notes</summary>
<p><em>Sourced from <a
href="https://github.com/softprops/action-gh-release/releases">softprops/action-gh-release's
releases</a>.</em></p>
<blockquote>
<h2>v2.0.0</h2>
<ul>
<li>update actions.yml declaration to node20 to address warnings</li>
</ul>
</blockquote>
</details>
<details>
<summary>Changelog</summary>
<p><em>Sourced from <a
href="https://github.com/softprops/action-gh-release/blob/master/CHANGELOG.md">softprops/action-gh-release's
changelog</a>.</em></p>
<blockquote>
<h2>0.1.12</h2>
<ul>
<li>fix bug leading to empty strings subsituted for inputs users don't
provide breaking api calls <a
href="https://redirect.github.com/softprops/action-gh-release/pull/144">#144</a></li>
</ul>
</blockquote>
</details>
<details>
<summary>Commits</summary>
<ul>
<li><a
href="72f2c25fcb"><code>72f2c25</code></a>
release 2.3.2</li>
<li><a
href="552dc5524b"><code>552dc55</code></a>
fix: revert <code>fs:readableWebStream</code> change (<a
href="https://redirect.github.com/softprops/action-gh-release/issues/632">#632</a>)</li>
<li><a
href="f3cad8bcbf"><code>f3cad8b</code></a>
release 2.3.1</li>
<li><a
href="07a2257003"><code>07a2257</code></a>
fix: fix file closing issue (<a
href="https://redirect.github.com/softprops/action-gh-release/issues/629">#629</a>)</li>
<li><a
href="d5382d3e6f"><code>d5382d3</code></a>
release 2.3.0</li>
<li><a
href="a0e2122208"><code>a0e2122</code></a>
feat: migrate from jest to vitest (<a
href="https://redirect.github.com/softprops/action-gh-release/issues/626">#626</a>)</li>
<li><a
href="8836085300"><code>8836085</code></a>
chore: replace <code>mime</code> with <code>mime-types</code> (<a
href="https://redirect.github.com/softprops/action-gh-release/issues/624">#624</a>)</li>
<li><a
href="86463358d8"><code>8646335</code></a>
chore: bump node to 20.19.2</li>
<li><a
href="46b284799f"><code>46b2847</code></a>
chore(deps): bump the npm group across 1 directory with 5 updates (<a
href="https://redirect.github.com/softprops/action-gh-release/issues/623">#623</a>)</li>
<li><a
href="37fd9d0351"><code>37fd9d0</code></a>
chore(deps): bump undici from 5.28.5 to 5.29.0 (<a
href="https://redirect.github.com/softprops/action-gh-release/issues/621">#621</a>)</li>
<li>Additional commits viewable in <a
href="https://github.com/softprops/action-gh-release/compare/v1...v2">compare
view</a></li>
</ul>
</details>
<br />


[![Dependabot compatibility
score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=softprops/action-gh-release&package-manager=github_actions&previous-version=1&new-version=2)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores)

Dependabot will resolve any conflicts with this PR as long as you don't
alter it yourself. You can also trigger a rebase manually by commenting
`@dependabot rebase`.

[//]: # (dependabot-automerge-start)
[//]: # (dependabot-automerge-end)

---

<details>
<summary>Dependabot commands and options</summary>
<br />

You can trigger Dependabot actions by commenting on this PR:
- `@dependabot rebase` will rebase this PR
- `@dependabot recreate` will recreate this PR, overwriting any edits
that have been made to it
- `@dependabot merge` will merge this PR after your CI passes on it
- `@dependabot squash and merge` will squash and merge this PR after
your CI passes on it
- `@dependabot cancel merge` will cancel a previously requested merge
and block automerging
- `@dependabot reopen` will reopen this PR if it is closed
- `@dependabot close` will close this PR and stop Dependabot recreating
it. You can achieve the same result by closing it manually
- `@dependabot show <dependency name> ignore conditions` will show all
of the ignore conditions of the specified dependency
- `@dependabot ignore this major version` will close this PR and stop
Dependabot creating any more for this major version (unless you reopen
the PR or upgrade to it yourself)
- `@dependabot ignore this minor version` will close this PR and stop
Dependabot creating any more for this minor version (unless you reopen
the PR or upgrade to it yourself)
- `@dependabot ignore this dependency` will close this PR and stop
Dependabot creating any more for this dependency (unless you reopen the
PR or upgrade to it yourself)


</details>
2025-08-19 02:04:50 -07:00
dependabot[bot]
330db6aef1 build(deps): Bump softprops/action-gh-release from 1 to 2
Bumps [softprops/action-gh-release](https://github.com/softprops/action-gh-release) from 1 to 2.
- [Release notes](https://github.com/softprops/action-gh-release/releases)
- [Changelog](https://github.com/softprops/action-gh-release/blob/master/CHANGELOG.md)
- [Commits](https://github.com/softprops/action-gh-release/compare/v1...v2)

---
updated-dependencies:
- dependency-name: softprops/action-gh-release
  dependency-version: '2'
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-08-18 01:15:03 +00:00
dependabot[bot]
cddfdf3ebc build(deps): Bump actions/checkout from 4 to 5
Bumps [actions/checkout](https://github.com/actions/checkout) from 4 to 5.
- [Release notes](https://github.com/actions/checkout/releases)
- [Changelog](https://github.com/actions/checkout/blob/main/CHANGELOG.md)
- [Commits](https://github.com/actions/checkout/compare/v4...v5)

---
updated-dependencies:
- dependency-name: actions/checkout
  dependency-version: '5'
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-08-18 01:14:28 +00:00
MSWS
deb0d2e825 feat: Refactor death action and add client event notification
```
- Update player death description in DeathAction to ensure clarity in scenarios involving a killer.
- Add Format method in DeathAction for structured death action descriptions.
- Implement client event notification in CombatHandler with conditional checks for attacker presence.
- Remove role initialization constructor in CS2Player to streamline code and refactor formatting.
```
2025-08-14 01:44:38 -07:00
MSWS
089564c4d6 feat: Differentiate win results and update role icons
- Adjust the logic in `RoundTimerListener.cs` to set final event results based on the winning team, assigning 2 for Counter-Terrorist wins and 3 for others, and refine win panel settings.
- Update `README.md` to reflect completed statuses for "Basic Gameplay," including the subcategories Traitors, Detectives, and Innocents, showcasing project progress.
- Reorder operations in `PlayerStatsTracker.cs` to update `PawnIsAlive` earlier in the `revealDeaths` method for clarity and consistent player state updates.
- Expand `RoleIconsHandler.cs` by adding `RevealIconFor` and `HideIconFor` methods to enhance control over traitor visual representation, allowing dynamic updates of player roles.
2025-08-14 01:31:45 -07:00
MSWS
871f47376a refactor: Improve state management and enhance role interactions
```
- Refine game start logic in RoundBasedGame.cs to ensure proper handling of game states and manage player notifications.
- Adjust state management and disposal process in RoundBasedGame.cs for better state handling and resource cleanup.
- Comment out deprecated EventRoundEnd logic in RoundTimerListener.cs and adjust timer settings for improved round transitions.
- Enhance BodyPickupListener.cs with new dependencies and logic for team adjustments during OnPropPickup events.
- Clean up PropMover.cs by removing unnecessary debug logging while maintaining current functionality.
```
2025-08-14 01:04:18 -07:00
MSWS
7621d15bcc feat: Improve round end handling and player status tracking
- Introduce a server command for handling win conditions during round end in `RoundTimerListener.cs`
- Wrap round end logic processing within a server update block in `RoundTimerListener.cs`
- Improve timing logic for round endings using `Observable.Timer` in `RoundTimerListener.cs`
- Ensure events/messages indicate the winner and specifics in `RoundTimerListener.cs`
- Update `PlayerStatsTracker.cs` to enhance pawn alive state tracking and accuracy
2025-08-14 00:42:33 -07:00
MSWS
a0111b5bea refactor: Refactor role logic and refine round timing events
- Modify `GameMsgs.cs` to enhance role identification through improved color coding and type checking for roles.
- Update `RoundTimerListener.cs` to incorporate reactive programming, improve event handling at round end, and refine role assignment logic.
- Enhance version string format in `TTTCommand.cs` by adding a short Git SHA for detailed version information.
- Simplify `EndRound` function in `RoundUtil.cs` by removing unnecessary delay parameter.
2025-08-14 00:33:43 -07:00
MSWS
14c4c85cfd refactor: Refactor connection and add pluralization tests
- Reorganize `connectToServer` method in `PlayerConnectionsHandler.cs` to delay certain operations until the next world update.
- Add player validity check before printing respawn chat message and update respawn logic to occur during the next world update in `PlayerConnectionsHandler.cs`.
- Consolidate respawn message to a generic "Respawning..." in `PlayerConnectionsHandler.cs`.
- Add new test cases in `ColoredRoleTest.cs` to verify pluralization functionality for role names, including special character handling.
- Ensure `HandlePluralization` method in `ColoredRoleTest.cs` correctly manages singular and plural forms with color formatting and dashes.
2025-08-13 23:41:32 -07:00
MSWS
e2383c90a8 fix: Invert game state check in OnDeath handler +semver:patch
- Correct logic in the `OnDeath` event handler by inverting the condition for an active game state check in `TTT/CS2/GameHandlers/BodySpawner.cs`
- Optimize function implementations including `makeGameRagdoll` and `correctRagdoll` in `TTT/CS2/GameHandlers/BodySpawner.cs`
2025-08-13 22:33:56 -07:00
MSWS
9db57d726d ci: Add webhook trigger for GitLab pipeline in nightly build
- Add `post_webhook` job to nightly workflow to trigger GitLab pipeline on `dev` branch
2025-08-13 22:14:18 -07:00
MSWS
47e63bf686 feat: Reuse active game in WAITING state +semver:patch
- Add condition in CS2GameManager to reuse active game if in WAITING state
2025-08-13 22:12:06 -07:00
MSWS
8835a76e67 feat: Enhance game state handling and player feedback
- Add `IGameManager` dependency to `PlayerConnectionsHandler.cs` for enhanced game state management
- Modify `connectToServer` in `PlayerConnectionsHandler.cs` to handle game states and improve player reconnection experience
- Update `DamageCanceler.cs` to improve conditional logic handling during active games
- Simplify player respawn logic and round handling in `RoundTimerListener.cs` by removing `PawnIsAlive` state manipulation and streamlining round start procedures
2025-08-13 20:45:08 -07:00
MSWS
731f58755d feat: Implement damage canceler and refine game logic
```
- Modify `RoundTimerListener` to reorder service initialization
- Add `TTT.API.Game` dependency to `BodySpawner` and improve game state checks and player handling upon death
- Reorder initialization logic in `SimpleLogger` for improved readability
- Introduce `GAME_LOGS_HEADER` and refactor message handling in `GameMsgs`
- Group minor organizational code changes across multiple files, including removing unused imports and restructuring logic for consistency
```
2025-08-13 20:01:48 -07:00
MSWS
824993fb16 refactor: Refactor 'PlayerPawn' references to 'Pawn' +semver:minor
- Improve error handling and modify references from `PlayerPawn` to `Pawn` in `BodySpawner.cs` to enhance robustness and reflect changes in the player object model.
- Update logic in `SimpleLogger.cs` to correctly set the `epoch` variable when the `timestamp` is smaller, fixing potential update issues.
- Refactor `PlayerExtensions.cs` for consistency by renaming variables from `PlayerPawn` to `Pawn` and ensure updated variable usage across player activities.
- Rename member from `PlayerPawn` to `Pawn` in `CS2InventoryManager.cs` to align with updated player data model and improve clarity.
- Update `TextSpawner.cs` references from `PlayerPawn` to `Pawn` for consistency and refactor list handling for better code alignment with new player data access method.
- Simplify `CombatHandler.cs` by changing references to `Pawn`, adjusting health updates, and improving code clarity for handling player events.
- Simplify and improve readability in `CS2Player.cs` by changing how player properties are accessed and set, maintaining debugging capabilities.
2025-08-13 18:38:43 -07:00
MSWS
6a67eb1141 Merge branch 'main' of github.com:MSWS/TTT 2025-08-13 10:55:09 -07:00
MSWS
670643998e Merge branch 'dev' 2025-08-13 10:55:03 -07:00
MSWS
70e2b44941 ci: Update workflows to use full semantic versioning
- Update `.github/workflows/release.yml` to use full semantic version (`fullSemVer`) in workflow steps
2025-08-13 10:52:59 -07:00
Isaac
c5cd646bee feat: Add PlayerStatsTracker and enhance game logic (#42)
- Implement `PlayerStatsTracker` to monitor player statistics using
dependency injection and event handlers for tracking kills, deaths, and
assists.
- Update `CS2ServiceCollection` to add `PlayerStatsTracker` listener for
enhanced player statistics tracking.
- Modify `RoundTimerListener` to incorporate player color settings at
round start and ensure proper player state updates.
- Enhance `CombatHandler` with game activity checks in
`OnPlayerDeath_Pre` and `OnPlayerHurt` methods to ensure efficient and
correct handling of game operations.
2025-08-13 10:49:12 -07:00
MSWS
223daa1085 feat: Add PlayerStatsTracker and enhance game logic
- Implement `PlayerStatsTracker` to monitor player statistics using dependency injection and event handlers for tracking kills, deaths, and assists.
- Update `CS2ServiceCollection` to add `PlayerStatsTracker` listener for enhanced player statistics tracking.
- Modify `RoundTimerListener` to incorporate player color settings at round start and ensure proper player state updates.
- Enhance `CombatHandler` with game activity checks in `OnPlayerDeath_Pre` and `OnPlayerHurt` methods to ensure efficient and correct handling of game operations.
2025-08-13 10:32:39 -07:00
MSWS
fbda4fe38b Merge branch 'dev' 2025-08-13 10:01:35 -07:00
MSWS
a663e556f9 ci: Simplify artifact zipping in release workflow
- Simplify artifact zipping process in release workflow by changing working directory to `build/TTT` before zipping.
2025-08-13 10:00:26 -07:00
Isaac
49d45a12b9 Refactor CS2 roles to use localization for coloring, add beam for prop dragging 2025-08-13 09:54:35 -07:00
MSWS
96b7b64634 Only upload TTT.zip 2025-08-13 09:50:49 -07:00
MSWS
fb00a5be2d ci: Zip artifacts and remove upload action step
- Replace the upload artifact step in `.github/workflows/release.yml` with a new step to zip artifacts using the current version from GitVersion.
2025-08-13 09:50:07 -07:00
MSWS
1374eeae76 feat: Integrate message localization into loggers
- Add dependency on `TTT.Locale` in `SimpleLogger.cs` for message localization
- Introduce `locale` field for localization in `SimpleLogger.cs`
- Update `PrintLogs` methods in `SimpleLogger.cs` to include localized headers
- Add `GAME_LOGS_HEADER` message type in `GameMsgs.cs` for enhanced log management
- Include "GAME_LOGS_HEADER" entry in `en.yml` for game log headers translation
- Adjust player assignment roles in `DamagedAction.cs` by swapping victim and attacker
2025-08-13 09:46:26 -07:00
MSWS
b52ab4b1c5 ci: Add build and release steps to workflows
```
- Update release workflow to build and restore Locale project, compiling for release and copying JSON files
- Add steps to restore and publish Plugin project, specifying output directory
- Introduce artifact upload step for TTT with error handling for missing files
- Update GitHub release creation to include build directory files in release assets
```
2025-08-13 09:35:08 -07:00
MSWS
6de97166b0 refactor: Refactor role locale handling and improve game start logic
- Delete `RoleLocale.cs` file, indicating potential refactoring or change in handling role localization
- Modify `CS2Game.cs` to allow the `Start` method to return a nullable `IObservable<long>`, incorporating early exit logic when state is not `WAITING`
- Adjust game state logic in `CS2Game.cs` to set state to `IN_PROGRESS` or `COUNTDOWN` based on countdown parameter presence
- Update `TTTCommand.cs` to append "-DEBUG" to version string in debug mode and respond with modified version string
2025-08-13 09:23:36 -07:00
MSWS
78f40ea541 feat: Refactor roles; enhance logging and commands +semver:minor
```
- Enhance body identification by setting player clan based on primary role in BodyPickupListener.
- Add a nullable `DateTime` field `epoch` to SimpleLogger for tracking initial log time and refactor log formatting.
- Refactor SetRoleCommand to use non-prefixed role classes and update role assignment mechanism.
- Implement Lerp and Slerp methods in VectorExtensions for advanced vector interpolation.
- Introduce StopCommand class to forcibly stop active games and manage game dependencies.
- Upgrade RoundTimerListener with role assignment logic and new event triggers on round end.
- Refactor RoleIconsHandler to use dictionaries for icon management and rename role classes.
- Remove CS2TraitorRole, CS2DetectiveRole, and CS2InnocentRole, indicating role refactoring.
- Add color formatting to role names in language files and improve message consistency.
- Enhance PropMover with visual effects for entity interactions and refine entity teleportation logic.
- Use C# 8 range indexer syntax in CS2Player for improved readability and concise logic.
```
2025-08-13 09:11:56 -07:00
MSWS
da40708d96 Create Release 2025-08-13 05:53:54 -07:00
MSWS
7a8ea2d6e7 Cleanup and Reformat 2025-08-13 05:44:51 -07:00
MSWS
12de87c6ea ci: Revamp release workflow for automation
- Rename workflow to "Auto Release on SemVer Change" and modify trigger to branch-based for "main" and "dev".
- Change job name to "auto-release" and remove .NET setup to streamline workflow.
- Update GitVersion to 6.3.x and centralize tag management with automatic tagging.
- Revamp changelog generation using GitHub API and update release creation process.
- Implement cleanup process for old pre-releases to maintain repository hygiene.
2025-08-13 05:39:07 -07:00
MSWS
6eb713b0e6 ci: Refactor release workflow for better efficiency.
- Update actions in `.github/workflows/release.yml` to latest versions
- Specify .NET version as 8.0.x for consistency
- Change release tag extraction to MajorMinorPatch format
- Improve logic for checking if tag commit is on the main branch
- Simplify previous tag identification for efficiency
- Implement dynamic range selection for release notes generation
- Ensure correct asset path is used for GitHub release creation
- Differentiate between release and prerelease versions based on branch check results
2025-08-13 05:20:53 -07:00
MSWS
497d5aa514 ci: Simplify versioning & enhance release notes generation.
- Update tag listing format and remove unnecessary comments in `.github/workflows/release.yml`
- Change versioning variables from `FullSemVer` to `MajorMinorPatch` for simpler versioning in `.github/workflows/release.yml`
- Add step to generate `release_notes.md` with a full commit list in `.github/workflows/release.yml`
- Modify release creation to use detailed release notes file in `.github/workflows/release.yml`
- Refine steps for tagged commits, tag range identification, and adjust artifact upload for versioning changes in `.github/workflows/release.yml`
2025-08-13 05:17:23 -07:00
MSWS
20b3b6abfb ci: Enhance version naming in release workflow
- Update GitHub Actions workflow to include full semantic version in ZIP package and artifact naming
- Modify artifact upload step to use `FullSemVer` for naming instead of `SemVer`
- Improve package ZIP step by using a single variable for full semantic version, enhancing consistency
- Introduce a comment to clarify full semantic version usage for asset naming in release creation
- Optimize variable usage by defining a `FULL` variable for full semantic version to reduce redundancy
2025-08-13 05:07:16 -07:00
MSWS
e355e080f9 ci: Enhance release workflow with ZIP packaging
- Remove comments from `release.yml` for brevity.
- Add conditional check in `release.yml` for missing language files.
- Introduce step in `release.yml` to package build directory as a ZIP.
- Modify artifact path in `release.yml` to use ZIP file.
- Change artifact name in `release.yml` to include semantic version.
- Add test to `release.yml` for asset existence before creating GitHub release.
2025-08-13 05:01:48 -07:00
MSWS
27ce64ce6c ci: Update actions and specify release asset path
- Update checkout action to `actions/checkout@v4` in release workflow
- Update .NET setup to `actions/setup-dotnet@v4` targeting .NET `8.0.x`
- Specify release asset to `build/TTT/TTT.zip` in release workflow
2025-08-13 04:57:23 -07:00
MSWS
1af0e86e18 ci: Enhance release workflow with updated actions
- Update checkout action to version 4 in release workflow
- Adjust setup .NET action to latest version 4 in release workflow
- Specify `if-no-files-found` behavior in upload artifact step
- Enhance tag commit check condition for main branch
- Improve logic for finding previous tag with fallback method
- Modify GitHub release creation step to upload artifacts directly from `build/TTT`
2025-08-13 04:55:28 -07:00
MSWS
d18904bcae ci: Refine release workflow configuration
- Update `actions/checkout` to latest version in `release.yml`
- Adjust .NET setup to "8.0.x" in `release.yml`
- Simplify artifact upload naming to `TTT.zip` in `release.yml`
- Refine release asset naming in GitHub release creation in `release.yml`
2025-08-13 04:51:49 -07:00
MSWS
4027782a09 ci: Refactor build and publish process in release workflow
- Modify build process in release workflow to include setting up the Locale project
- Change build step to focus on "Build Locale" and specify output directory for language JSON files
- Revise packaging step to "Publish Plugin" for the TTT Plugin project
- Reorganize upload process by renaming artifact to "TTT" and omitting versioning from file path
- Remove retention-days configuration from workflow artifact upload step
2025-08-13 04:45:09 -07:00
Isaac
28a330ea4d Role assignment overhaul via IRoleAssigner, body identification, text rendering (#40) 2025-08-13 04:31:04 -07:00
MSWS
2029d6e940 Resolve compiler error 2025-08-13 04:27:49 -07:00
Isaac
2db293adbc Update TTT/Game/Roles/RoleAssigner.cs
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
Signed-off-by: Isaac <14448584+MSWS@users.noreply.github.com>
2025-08-13 04:25:11 -07:00
Isaac
c84072d705 Update TTT/Game/lang/GameMsgs.cs
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
Signed-off-by: Isaac <14448584+MSWS@users.noreply.github.com>
2025-08-13 04:23:36 -07:00
Isaac
2fabe3a680 Update TTT/Shop/PlayerKillListener.cs
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
Signed-off-by: Isaac <14448584+MSWS@users.noreply.github.com>
2025-08-13 04:22:57 -07:00
MSWS
9478950da9 ci: Simplify release workflow; trigger on tag push
- Update `.github/workflows/release.yml` to trigger on any tag push, removing dependency on other workflows
- Simplify concurrency settings by using GitHub reference name
- Add permissions section to grant write access to contents
- Combine separate jobs into a single `build-and-release` job
- Update to `actions/checkout@v4`, removing ref specification
- Change GitVersion setup to a lower version (v3) and update version spec
- Streamline versioning by removing detailed semantic checks
- Add build step utilizing .NET to restore packages and publish application
- Create and upload zip package of published artifact as a workflow artifact
- Enhance release creation logic, simplifying tag generation and pre-release handling
- Remove redundant artifact renaming, changelog generation, and old release pruning steps

Overall, these changes simplify and enhance the flexibility of the release process.
2025-08-13 04:22:10 -07:00
MSWS
8952d009fd feat: Enhance player conversion in BodyPickupListener
- Add dependency for `IPlayerConverter<CCSPlayerController>` in `BodyPickupListener.cs`
- Enhance `OnPropPickup` to convert attached player to an online player using the new converter
- Implement validity check for converted online player
- Update online player's pawn state to not alive upon body identification
- Invoke utility function to set `CCSPlayerController` pawn status change
2025-08-13 04:13:43 -07:00
MSWS
5661588e1e refactor: Improve debug messages and role visual feedback
- Reformat debug messages in `CS2Messenger.cs` for improved readability and structure.
- Update color for `ColoredRole` name in `ColoredRoleTest.cs` from red to dark blue.
- Enhance efficiency and clarity in `StringLocalizer.cs` by refining placeholder handling and vowel sound logic.
- Add color-coding to role identification in `GameMsgs.cs` to improve visual feedback during player identification.
- Adjust interaction distance and improve state management in `PropMover.cs` for better control and performance.
2025-08-13 04:09:15 -07:00
MSWS
9667a519f1 feat: Enhance logging and modular command system
```
Enhance Game Functionality and Logging Capabilities

- Update `GameMsgs.cs` to utilize explicit `Name` properties for data retrieval and introduce a new dependency on `CounterStrikeSharp.API.Modules.Utils`.
- Modify `PropMover.cs` to adjust minimum look accuracy, improving precision requirements.
- Extend `SimpleLogger.cs` with new logging methods for individual and all players, enhancing overall logging functionality.
- Revise `CS2CommandManager.cs` to improve code base structure by removing redundancy and ensuring correct method order.
- Update `CommandManager.cs` by implementing `ITerrorModule`, adding modularity and logging command capabilities.
- Enhance `IActionLogger.cs` with new logging methods integrating player functionalities.
- Introduce `LogsCommand.cs` to manage and display active game logs with error handling for inactive games.
- Adjust `StringLocalizer.cs` to refine character evaluation in text handling.
- Revise `en.yml` color schemes for consistency in message display.
- Simplify `GameEndLogsListener.cs` for better efficiency by using `PrintLogs()` method.
- Introduce a new 'MONITOR' priority level in `EventHandlerAttribute.cs` for more granular event handling priorities.
```
2025-08-13 03:06:47 -07:00
MSWS
00c8ad318b feat: Introduce body identification feature
- Rename `GameMsgs.cs` and restructure to `lang` directory; add `BODY_IDENTIFIED` message method for body identification scenarios.
- Implement `IdentifyBodyAction` class for handling body identification events, enhancing game event handling.
- Move CS2 messaging structures to `lang` directories for improved organization.
- Update `SpectatorRole.cs` to reflect new `lang` namespace.
- Replace `GamePlayerActionsListener` with `PlayerActionsLogger` in `PlayerActionsTest.cs`, integrating new logging functionality.
- Enhance game service collections with new listeners, including `PlayerActionsLogger` and `BodyIdentifyLogger`.
- Implement `BodyIdentifyLogger` to log body identification events.
- Enhance `BodyPickupListener` with improved error handling and localized messaging.
- Add new localized message format in `en.yml` for body identification events.
- Transform `GamePlayerActionsListener` to `PlayerActionsLogger` with updated structure and logging focus.
2025-08-13 02:29:26 -07:00
MSWS
e1f2d0e77a refactor: Refactor role management using IRoleAssigner
Refactor role management and simplify codebase

- **RoleAssignerTest.cs**: Update tests to use `assigner.GetRoles(p)` for role retrieval, ensuring consistency across tests.
- **Program.cs**: Remove error handling for YAML parsing, maintaining functionality in argument parsing and JSON conversion.
- **RoundBasedGameTest.cs**: Integrate `IRoleAssigner`, modifying role checks and simplifying test assertions.
- **IGame.cs**: Add `RoleAssigner` property and refactor role retrieval methods to streamline role management.
- **Multiple Files**: Implement `IRoleAssigner` across various components, enhancing role management consistency and simplifying code by removing direct role access.
2025-08-13 02:08:49 -07:00
MSWS
cf7a93925b refactor: Rename GameConfig to TTTConfig for consistency
```
Update configuration handling and improve code consistency

- Update `RoundBasedGame.cs` to use `TTTConfig`, enhancing game lifecycle management and state transitions.
- Rename `GameConfig.cs` to `TTTConfig.cs` for consistency, with no changes to logic or properties.
- Refactor `CS2CommandManager.cs` to clean up command registration and improve readability.
- Adjust `PlayerConnectionsHandler.cs` to simplify server update logic and remove unnecessary checks.
- Improve `RoleAssignListener.cs` for better role assignment handling and ensure proper player role transitions.

Additionally, minor updates are made across multiple files to replace `GameConfig` with `TTTConfig`, ensuring consistent configuration handling throughout the codebase.
```
2025-08-12 23:25:05 -07:00
MSWS
01231d29e6 Update namespaces 2025-08-12 20:56:21 -07:00
MSWS
5237ff1f64 feat: Implement role assignment and weapon handling updates
```
Implement Various Enhancements and Refactoring Across Multiple Modules

- Update RoleAssignListener.cs: Remove unused imports, add module metadata with new public properties, and reorganize method structure for clarity. Implement new Start method and improve efficiency in onTransmit logic.
- Optimize SimpleLogger.cs by utilizing full date and time for dictionary keys, enhancing logging precision.
- Adjust role assignment process in BaseRole.cs, TraitorRole.cs, DetectiveRole.cs, and InnocentRole.cs to conditionally strip weapons based on new GameConfig.cs setting, StripWeaponsPriorToEquipping.
- Refine SetRoleCommand.cs by reorganizing imports and enhancing role assignment logic, ensuring dynamic role selection and clear messaging.
- Enhance RoundBasedGame.cs with new inventory management component to standardize player inventories at the start of each round and leverage dependency injection for external services.
- Conduct miscellaneous refactorings and performance improvements, including test updates, import optimizations, and enhanced logging across multiple files.
```
2025-08-12 02:49:00 -07:00
MSWS
4c4c4290ad Clear cache on round start 2025-08-11 20:31:13 -07:00
MSWS
7b79182fdf feat: Enhance role assignment and command features
```
- Enhance messaging functionality in `BaseRole.cs` with new `IMessenger` dependency and localized player notifications during role assignment.
- Update `CS2CommandManager.cs` to include new `SetRoleCommand` and refine command management namespace.
- Extend `RoleAssignListener` in `RoleAssignListener.cs` to include role identification and icon management for `CS2TraitorRole`, implementing `IPluginModule`.
- Shift role assignment notifications in `RoleAssigner.cs` from player-specific to global messaging for improved game transparency.
- Refactor `CS2ServiceCollection.cs` to use a new `RoleAssignListener` behavior, optimizing role management practices.
```
2025-08-11 20:03:01 -07:00
MSWS
6f61c81bed feat: Introduce text rendering and spawning features +semver:minor
```
- Rename and reorganize several files for improved project structure, including `CS2Messenger.cs`, `CS2InventoryManager.cs`, `CS2CommandInfo.cs`, `CCPlayerConverter.cs`, `CS2Msgs.cs`, `TestCommand.cs`, and `CS2CommandManager.cs`.
- Add new methods to `VectorExtensions.cs` for vector normalization and scaling, and suppress code analysis warnings.
- Introduce `TextSetting.cs` class for text rendering, defining properties like color, font, justification, and orientation.
- Enhance `PropMover.cs` with new utility imports, increase interaction parameters, remove outdated array logic, add logging, and improve teleport logic.
- Expand `RoleAssignListener.cs` with new `using` directives, implement `ITextSpawner`, replace player color settings, and create text hat during role assignments.
- Introduce `TraceFlags` enum in `RayTrace.cs` to improve mask clarity and refactor vector operations for consistency.
- Implement `TextSpawner.cs`, adhering to `ITextSpawner` interface, to create and manage in-game text entities and associated error handling.
- Optimize `BodySpawner.cs` ragdoll correction with efficient update logic and improved rotation use.
- Define `ITextSpawner` interface for flexible text and text hat creation methods, improving in-game text mechanics.
```
2025-08-11 19:17:24 -07:00
MSWS
63bb22fd43 docs: Include discord invite link in README 2025-08-11 04:22:54 -07:00
Isaac
9da822348d build(deps): Bump actions/download-artifact from 4 to 5 (#38)
Bumps
[actions/download-artifact](https://github.com/actions/download-artifact)
from 4 to 5.
<details>
<summary>Release notes</summary>
<p><em>Sourced from <a
href="https://github.com/actions/download-artifact/releases">actions/download-artifact's
releases</a>.</em></p>
<blockquote>
<h2>v5.0.0</h2>
<h2>What's Changed</h2>
<ul>
<li>Update README.md by <a
href="https://github.com/nebuk89"><code>@​nebuk89</code></a> in <a
href="https://redirect.github.com/actions/download-artifact/pull/407">actions/download-artifact#407</a></li>
<li>BREAKING fix: inconsistent path behavior for single artifact
downloads by ID by <a
href="https://github.com/GrantBirki"><code>@​GrantBirki</code></a> in <a
href="https://redirect.github.com/actions/download-artifact/pull/416">actions/download-artifact#416</a></li>
</ul>
<h2>v5.0.0</h2>
<h3>🚨 Breaking Change</h3>
<p>This release fixes an inconsistency in path behavior for single
artifact downloads by ID. <strong>If you're downloading single artifacts
by ID, the output path may change.</strong></p>
<h4>What Changed</h4>
<p>Previously, <strong>single artifact downloads</strong> behaved
differently depending on how you specified the artifact:</p>
<ul>
<li><strong>By name</strong>: <code>name: my-artifact</code> → extracted
to <code>path/</code> (direct)</li>
<li><strong>By ID</strong>: <code>artifact-ids: 12345</code> → extracted
to <code>path/my-artifact/</code> (nested)</li>
</ul>
<p>Now both methods are consistent:</p>
<ul>
<li><strong>By name</strong>: <code>name: my-artifact</code> → extracted
to <code>path/</code> (unchanged)</li>
<li><strong>By ID</strong>: <code>artifact-ids: 12345</code> → extracted
to <code>path/</code> (fixed - now direct)</li>
</ul>
<h4>Migration Guide</h4>
<h5> No Action Needed If:</h5>
<ul>
<li>You download artifacts by <strong>name</strong></li>
<li>You download <strong>multiple</strong> artifacts by ID</li>
<li>You already use <code>merge-multiple: true</code> as a
workaround</li>
</ul>
<h5>⚠️ Action Required If:</h5>
<p>You download <strong>single artifacts by ID</strong> and your
workflows expect the nested directory structure.</p>
<p><strong>Before v5 (nested structure):</strong></p>
<pre lang="yaml"><code>- uses: actions/download-artifact@v4
  with:
    artifact-ids: 12345
    path: dist
# Files were in: dist/my-artifact/
</code></pre>
<blockquote>
<p>Where <code>my-artifact</code> is the name of the artifact you
previously uploaded</p>
</blockquote>
<p><strong>To maintain old behavior (if needed):</strong></p>
<pre lang="yaml"><code>&lt;/tr&gt;&lt;/table&gt; 
</code></pre>
</blockquote>
<p>... (truncated)</p>
</details>
<details>
<summary>Commits</summary>
<ul>
<li><a
href="634f93cb29"><code>634f93c</code></a>
Merge pull request <a
href="https://redirect.github.com/actions/download-artifact/issues/416">#416</a>
from actions/single-artifact-id-download-path</li>
<li><a
href="b19ff43027"><code>b19ff43</code></a>
refactor: resolve download path correctly in artifact download tests
(mainly ...</li>
<li><a
href="e262cbee4a"><code>e262cbe</code></a>
bundle dist</li>
<li><a
href="bff23f9308"><code>bff23f9</code></a>
update docs</li>
<li><a
href="fff8c148a8"><code>fff8c14</code></a>
fix download path logic when downloading a single artifact by id</li>
<li><a
href="448e3f862a"><code>448e3f8</code></a>
Merge pull request <a
href="https://redirect.github.com/actions/download-artifact/issues/407">#407</a>
from actions/nebuk89-patch-1</li>
<li><a
href="47225c44b3"><code>47225c4</code></a>
Update README.md</li>
<li>See full diff in <a
href="https://github.com/actions/download-artifact/compare/v4...v5">compare
view</a></li>
</ul>
</details>
<br />


[![Dependabot compatibility
score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=actions/download-artifact&package-manager=github_actions&previous-version=4&new-version=5)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores)

Dependabot will resolve any conflicts with this PR as long as you don't
alter it yourself. You can also trigger a rebase manually by commenting
`@dependabot rebase`.

[//]: # (dependabot-automerge-start)
[//]: # (dependabot-automerge-end)

---

<details>
<summary>Dependabot commands and options</summary>
<br />

You can trigger Dependabot actions by commenting on this PR:
- `@dependabot rebase` will rebase this PR
- `@dependabot recreate` will recreate this PR, overwriting any edits
that have been made to it
- `@dependabot merge` will merge this PR after your CI passes on it
- `@dependabot squash and merge` will squash and merge this PR after
your CI passes on it
- `@dependabot cancel merge` will cancel a previously requested merge
and block automerging
- `@dependabot reopen` will reopen this PR if it is closed
- `@dependabot close` will close this PR and stop Dependabot recreating
it. You can achieve the same result by closing it manually
- `@dependabot show <dependency name> ignore conditions` will show all
of the ignore conditions of the specified dependency
- `@dependabot ignore this major version` will close this PR and stop
Dependabot creating any more for this major version (unless you reopen
the PR or upgrade to it yourself)
- `@dependabot ignore this minor version` will close this PR and stop
Dependabot creating any more for this minor version (unless you reopen
the PR or upgrade to it yourself)
- `@dependabot ignore this dependency` will close this PR and stop
Dependabot creating any more for this dependency (unless you reopen the
PR or upgrade to it yourself)


</details>
2025-08-11 04:21:26 -07:00
Isaac
4cd18c7ae8 build(deps): Bump GitTools/actions from 4.0.1 to 4.1.0 (#39)
Bumps [GitTools/actions](https://github.com/gittools/actions) from 4.0.1
to 4.1.0.
<details>
<summary>Release notes</summary>
<p><em>Sourced from <a
href="https://github.com/gittools/actions/releases">GitTools/actions's
releases</a>.</em></p>
<blockquote>
<h2>v4.1.0</h2>
<p>As part of this release we had <a
href="https://github.com/GitTools/actions/compare/v4.0.1...v4.1.0">64
commits</a> which resulted in <a
href="https://github.com/GitTools/actions/milestone/4?closed=1">6
issues</a> being closed.</p>
<p><strong>Bugs</strong></p>
<ul>
<li>[<strong><a
href="https://redirect.github.com/gittools/actions/issues/1685">#1685</a></strong>](<a
href="https://redirect.github.com/GitTools/actions/issues/1685">GitTools/actions#1685</a>)
[ISSUE]: Release 4.0.0 - Cannot parse local nuget sources</li>
<li><a
href="https://redirect.github.com/GitTools/actions/pull/1716"><strong>!1716</strong></a>
<a
href="https://redirect.github.com/gittools/actions/issues/1676">#1676</a>
- fix -GitVersion configuration file not found at&quot;</li>
<li><a
href="https://redirect.github.com/GitTools/actions/pull/1722"><strong>!1722</strong></a>
<a
href="https://redirect.github.com/gittools/actions/issues/1676">#1676</a>
- Fixes file path validation in dotnet tool</li>
</ul>
<p><strong>Documentation</strong></p>
<ul>
<li><a
href="https://redirect.github.com/GitTools/actions/pull/1693"><strong>!1693</strong></a>
Improved instructions about cloning</li>
<li><a
href="https://redirect.github.com/GitTools/actions/pull/1712"><strong>!1712</strong></a>
Fix typo in setup.md</li>
</ul>
<h3>SHA256 Hashes of the release artifacts</h3>
<ul>

<li><code>0343c0ac8f67bd00d96fbc237051f7fe0b7ad335c75a0b71e4f4a7daba5a1ed8
- gittools.gittools-4.1.0.250805235.vsix</code></li>
</ul>
</blockquote>
</details>
<details>
<summary>Commits</summary>
<ul>
<li><a
href="b82e662a71"><code>b82e662</code></a>
Merge pull request <a
href="https://redirect.github.com/gittools/actions/issues/1722">#1722</a>
from arturcic/fix/1676</li>
<li><a
href="084f803b7a"><code>084f803</code></a>
<a
href="https://redirect.github.com/gittools/actions/issues/1676">#1676</a>
- Fixes file path validation in dotnet tool</li>
<li><a
href="1d898d18d1"><code>1d898d1</code></a>
Merge pull request <a
href="https://redirect.github.com/gittools/actions/issues/1721">#1721</a>
from arturcic/feature/azdo-tasks-updates</li>
<li><a
href="558b87e803"><code>558b87e</code></a>
updates azure tasks and fixes date format</li>
<li><a
href="226eef0291"><code>226eef0</code></a>
Merge pull request <a
href="https://redirect.github.com/gittools/actions/issues/1713">#1713</a>
from GitTools/dependabot/npm_and_yarn/typescript-5.9.2</li>
<li><a
href="ac62f3483b"><code>ac62f34</code></a>
(npm): Bump typescript from 5.8.3 to 5.9.2</li>
<li><a
href="bd57eebbb9"><code>bd57eeb</code></a>
Merge pull request <a
href="https://redirect.github.com/gittools/actions/issues/1720">#1720</a>
from GitTools/dependabot/npm_and_yarn/eslint-801ca537e1</li>
<li><a
href="a5fed8da22"><code>a5fed8d</code></a>
(npm): Bump typescript-eslint from 8.38.0 to 8.39.0 in the eslint
group</li>
<li><a
href="61dcb54ac9"><code>61dcb54</code></a>
Terminal <a
href="https://redirect.github.com/gittools/actions/issues/1676">#1676</a>
- fix -GitVersion configuration file not found at&quot;</li>
<li><a
href="6bac175d2b"><code>6bac175</code></a>
Merge pull request <a
href="https://redirect.github.com/gittools/actions/issues/1717">#1717</a>
from arturcic/main</li>
<li>Additional commits viewable in <a
href="https://github.com/gittools/actions/compare/v4.0.1...v4.1.0">compare
view</a></li>
</ul>
</details>
<br />


[![Dependabot compatibility
score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=GitTools/actions&package-manager=github_actions&previous-version=4.0.1&new-version=4.1.0)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores)

Dependabot will resolve any conflicts with this PR as long as you don't
alter it yourself. You can also trigger a rebase manually by commenting
`@dependabot rebase`.

[//]: # (dependabot-automerge-start)
[//]: # (dependabot-automerge-end)

---

<details>
<summary>Dependabot commands and options</summary>
<br />

You can trigger Dependabot actions by commenting on this PR:
- `@dependabot rebase` will rebase this PR
- `@dependabot recreate` will recreate this PR, overwriting any edits
that have been made to it
- `@dependabot merge` will merge this PR after your CI passes on it
- `@dependabot squash and merge` will squash and merge this PR after
your CI passes on it
- `@dependabot cancel merge` will cancel a previously requested merge
and block automerging
- `@dependabot reopen` will reopen this PR if it is closed
- `@dependabot close` will close this PR and stop Dependabot recreating
it. You can achieve the same result by closing it manually
- `@dependabot show <dependency name> ignore conditions` will show all
of the ignore conditions of the specified dependency
- `@dependabot ignore this major version` will close this PR and stop
Dependabot creating any more for this major version (unless you reopen
the PR or upgrade to it yourself)
- `@dependabot ignore this minor version` will close this PR and stop
Dependabot creating any more for this minor version (unless you reopen
the PR or upgrade to it yourself)
- `@dependabot ignore this dependency` will close this PR and stop
Dependabot creating any more for this dependency (unless you reopen the
PR or upgrade to it yourself)


</details>
2025-08-11 04:19:46 -07:00
MSWS
f09ad09c33 feat: Implement body and prop event systems +semver:minor
```
- Organize and restructure project files by moving core game files to a new "Game" directory.
- Introduce the `BodyEvent` abstract class and multiple body-related event classes such as `BodyIdentifyEvent` and `BodyCreateEvent` for enhanced event handling.
- Implement the `BodySpawner.cs` file, introducing the `BodySpawner` class with robust logic for body spawning, event handling, and game services integration.
- Refactor `VectorExtensions.cs` by changing data types for performance improvements and adding utility methods for vector manipulation.
- Enhance `CombatHandler.cs` with new events `PlayerDeathEvent` and `PlayerDamagedEvent`, correcting spelling errors, and refining player state handling.
- Develop new interface `IBody` and class `CS2Body` to manage game character bodies, including properties and methods for player associations.
- Expand event handling capabilities with the addition of `PropPickupEvent` and `PropDropEvent` classes, supporting cancellable game events.
- Refactor `PropMover.cs` to simplify code, improve efficiency with LINQ, and integrate debug statements and event dispatching.
- Remove the `BodyHider.cs` file, indicating a shift in handling player color changes within the game.
```
2025-08-11 04:12:16 -07:00
dependabot[bot]
3644dfb2bc build(deps): Bump GitTools/actions from 4.0.1 to 4.1.0
Bumps [GitTools/actions](https://github.com/gittools/actions) from 4.0.1 to 4.1.0.
- [Release notes](https://github.com/gittools/actions/releases)
- [Changelog](https://github.com/GitTools/actions/blob/main/GitReleaseManager.yml)
- [Commits](https://github.com/gittools/actions/compare/v4.0.1...v4.1.0)

---
updated-dependencies:
- dependency-name: GitTools/actions
  dependency-version: 4.1.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-08-11 01:01:16 +00:00
dependabot[bot]
f8ccdd88af build(deps): Bump actions/download-artifact from 4 to 5
Bumps [actions/download-artifact](https://github.com/actions/download-artifact) from 4 to 5.
- [Release notes](https://github.com/actions/download-artifact/releases)
- [Commits](https://github.com/actions/download-artifact/compare/v4...v5)

---
updated-dependencies:
- dependency-name: actions/download-artifact
  dependency-version: '5'
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-08-11 01:01:11 +00:00
Isaac
0b028b4d99 Overhaul CI (#37) 2025-08-10 01:18:08 -07:00
MSWS
3f36a5e8ea Fix indentation 2025-08-10 01:09:19 -07:00
MSWS
d11e4189a1 Attempt to fix workflow issue 2025-08-10 01:07:58 -07:00
MSWS
17527059c0 ci: Revise changelog and release workflows
- Revise the changelog template in `.github/changelogConfig.json` to include contributors, commit details, and sorting capabilities.
- Simplify syntax and modify concurrency setting in `.github/workflows/release.yml`, and add logical enhancements for version comparison and release conditions.
2025-08-10 01:04:53 -07:00
Isaac
90ce56e888 More shop management and game integration (#36) 2025-08-10 00:20:35 -07:00
MSWS
624b405e98 Reformat 2025-08-09 21:49:36 -07:00
MSWS
a73c3752a7 Import regex in Test module 2025-08-09 21:14:54 -07:00
MSWS
26b724fdcb Add Copilot suggestions 2025-08-09 21:11:10 -07:00
Isaac
2c11cc6652 Update TTT/Test/Game/Round/RoundBasedGameTest.cs
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
Signed-off-by: Isaac <14448584+MSWS@users.noreply.github.com>
2025-08-09 21:07:54 -07:00
Isaac
ee299846df Update TTT/CS2/Extensions/VectorExtensions.cs
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
Signed-off-by: Isaac <14448584+MSWS@users.noreply.github.com>
2025-08-09 21:07:08 -07:00
Isaac
c221a774bb Update TTT/CS2/GameHandlers/PropMover.cs
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
Signed-off-by: Isaac <14448584+MSWS@users.noreply.github.com>
2025-08-09 21:04:07 -07:00
MSWS
bd2ffa951e Reformat & Cleanup, add README to Versioning 2025-08-08 02:03:41 -07:00
MSWS
073634c2f7 feat: Refactor ragdoll management and enhance game handling
- Remove the "body" command case and related functionality from `TestCommand.cs`.
- Update `RoundBasedGame.cs` to finalize game state changes upon disposal.
- Overhaul entity interaction and initialization logic in `PropMover.cs`, refine event handling, and introduce enhanced movement tracking using the new `MovementInfo` class.
- Create `MovementInfo.cs` for data handling of entity movement.
- Experimentally disable player connection event dispatching in `PlayerConnectionsHandler.cs`.
- Re-enable `CombatHandler` and add new `BodyHider` plugin behavior in `CS2ServiceCollection.cs`.
- Implement new `BodyHider` module for altering player visibility and enhancing death event handling.
2025-08-07 22:10:58 -07:00
MSWS
bc5b0b6770 feat: Fix DistanceSquared calc and enhance PropMover interactions +semver:minor
```
- Correct the calculation in the `DistanceSquared` method in `VectorExtensions.cs` to properly compute squared Euclidean distance between two vectors.
- Add new extension and vector utilities in `PropMover.cs`.
- Change type in the dictionary and hashset in `PropMover.cs` from `CEntityInstance` to `CBaseEntity`.
- Revise entity addition condition in `PropMover.cs` using specific logic based on entity type.
- Enhance interaction feedback and implement distance-based detection for player interaction with entities in `PropMover.cs`.
```
2025-08-07 13:38:30 -07:00
MSWS
344e5ebe62 feat: Implement prop movement and ray tracing features +semver:minor
```
- Enhance `PropMover.cs` with new event listeners and interaction logic, including player button handling and entity filtering.
- Enable unsafe code in `CS2.csproj` for potential performance improvements.
- Add vector extension methods in `VectorExtensions.cs` to compute distances, aiding geometric calculations.
- Introduce `PropMover` plugin in `CS2ServiceCollection.cs` and reorder handlers, with a note on missing final newline.
- Implement ray tracing in `RayTrace.cs`, including error handling and low-level API interaction for precision in trace calculations.
```
2025-08-07 12:36:43 -07:00
MSWS
f0b896120f Resolve merge conflicts 2025-08-07 11:39:42 -07:00
MSWS
6901e47fe0 Get scoreboard spoofing working 2025-08-07 11:37:26 -07:00
MSWS
2f5b4c4822 Reformat & Cleanup 2025-08-06 23:38:42 -07:00
MSWS
f295786887 refactor: Refactor round termination logic in utils and listener
- Introduce a new `TerminateRoundFunc` in `RoundUtil.cs` with game data signature and update `EndRound` to use it.
- Simplify null checks in `RoundUtil.cs` by removing redundant variable declarations and handle potential null values for `ServerUtil.GameRulesProxy`.
- Remove inline comments in `RoundUtil.cs` for better readability.
- Add `JetBrains.Annotations` import and `[UsedImplicitly]` annotations in `RoundTimerListener.cs`.
- Remove `IPlayerFinder` dependency and replace `TerminateRoundFunc` with `RoundUtil.EndRound` in `RoundTimerListener.cs`, enhancing readability and simplifying class structure.
2025-08-06 23:19:27 -07:00
MSWS
c52672e2b0 feat: Refactor and enhance round management logic
- Implement respawn mechanism for non-alive players during countdown in `RoundTimerListener.cs`.
- Adjust command execution logic and set dynamic round time based on player count in `RoundTimerListener.cs`.
- Change team assignments for `InnocentRole` players at round end in `RoundTimerListener.cs`.
- Rename `ServerExtensions.cs` to `ServerUtil.cs`, and update class and namespace to match in `ServerUtil.cs`.
- Add new utility imports in `CS2Game.cs` and `RoundUtil.cs`.
2025-08-06 23:11:41 -07:00
MSWS
d5d7a646b1 refactor: Refactor game rules access for improved clarity
- Replace `GetGameRules()` method with `GameRules` property in `ServerExtensions.cs` and introduce caching for improved efficiency.
- Update `RoundTimerListener.cs` to use `GameRulesProxy` property for simplified and direct access to game rules.
- Simplify `RoundUtil.cs` by replacing method calls with property accesses for enhanced clarity and code readability.
2025-08-06 23:08:16 -07:00
MSWS
37b21fd46d feat: Add shop feature with balance clearing test +semver:minor
- Add using directive for `TTT.Shop` and scoped service registration for `IShop` in `Startup.cs`
- Create `BalanceClearTest` class to ensure balances are cleared at game start
- Reformat XAML elements and add code coverage filter in `TTT.sln.DotSettings`
- Add project reference to `Shop.csproj` in `Test.csproj`
- Change type from `IOnlinePlayer` to `IPlayer` in `IShop` and `Shop` classes
2025-08-06 22:59:23 -07:00
MSWS
680bb3789e docs: Add badges to README for clarity and updates
- Add a styled badge link to the top of the README
- Rename code coverage badge to "Code Coverage" for clarity
- Introduce a new badge displaying development time with specific request parameters
2025-08-06 22:37:40 -07:00
MSWS
d92996d11e ci: Prevent CI execution of GitVersion generation +semver:minor
Add condition to GenerateGitVersionInformation target in Versioning.csproj

- Prevent execution in continuous integration environments by adding a condition to the GenerateGitVersionInformation target in Versioning.csproj.
2025-08-06 22:31:06 -07:00
MSWS
7f6e9359aa refactor: Refactor code for readability and maintainability +semver:patch
```
Refactor codebase for improved readability, maintainability, and performance

- TTT/CS2/GameHandlers/CombatHandler.cs: Remove unused directives, reorder methods, and apply minor formatting changes.
- TTT/Game/RoundBasedGame.cs: Optimize `Start` method logic, improve game state transitions, enhance messaging logic, and ensure proper resource cleanup.
- TTT/CS2/CS2InventoryManager.cs: Refine `RemoveWeapon` function by cleaning up parameters and improving weapon removal handling.
- TTT/API/Game/IGame.cs: Rename `GetRole` to `GetOfRole` and enhance `GetAlive` method flexibility with new parameters.
- TTT/Plugin/TTT.cs: Eliminate unused library references for cleaner code.
- Various Files: Remove unused directives, reorder methods for better readability, and improve file organization across multiple files.
```
2025-08-06 22:27:39 -07:00
MSWS
7ec2554bc3 test: Add ColoredRole tests with xUnit for article handling +semver:minor
- Introduce a new test class `ColoredRoleTest` for the `ColoredRole` within a structured namespace.
- Implement the `ColoredRole` class that derives from `IRole` with a red-colored name demonstration.
- Add unit tests using xUnit framework to verify correct article usage in role assignment messages.
- Utilize dependency injection to obtain `IMsgLocalizer` for localization testing.
2025-08-06 22:24:02 -07:00
MSWS
edeb0e08b8 fix: Enable Git version info and fix JSON null handling
- Un-comment the `GenerateGitVersionInformation` target in `Versioning.csproj` to enable version information generation on non-Windows systems.
- Remove the execution command previously used to compile and run the project in `Versioning.csproj`.
- Adjust the path for the generated `gitversion.json` file in `Versioning.csproj`, moving it one directory up.
- Update `Program.cs` to change the handling of null JSON values by assigning an empty string for string type, while keeping other JSON value conversions unchanged.
2025-08-06 22:15:35 -07:00
MSWS
45ad0375e5 Remove WIP 2025-08-06 21:33:16 -07:00
MSWS
e8169a54b1 feat: Remove entity event delay; add player checks & command
- Modify `AddEntityIOEvent` in `CS2InventoryManager.cs` by removing the delay parameter, potentially changing event timing execution
- Add null and validity check for player pawn in `RoleAssignListener.cs` to ensure it exists and is valid before calling `SetModel()`
- Introduce `TestCommand` class in `TestCommand.cs` with command execution logic and asynchronous task handling
- Integrate `TestCommand` in `CS2CommandManager.cs` with `hotReload` parameter and expanded command registration process
2025-08-06 20:04:40 -07:00
MSWS
692d233ac0 feat: Implement game state handling and round logic +semver:minor
```
Introduce new game mechanics and improve resource management

- Update `TTT.cs` to enhance Dispose method, ensuring cleanup of IGameManager resources.
- Add `RoundStartHandler.cs` with essential round start logic and dependency management.
- Expand `PlayerCausesEndListener.cs` with improved role handling and debug logging.
- Modify `CS2Game.cs` to integrate reactive programming for countdowns and state management.
- Optimize `CS2Player.cs` with consolidated logic for player identification and state checks.
- Refactor `RoundBasedGame.cs` to include localized messaging and enhanced game state handling.
- Update multiple game configuration files with new endgame message templates and listener adjustments.
```
2025-08-06 19:13:59 -07:00
MSWS
fa31a6b492 test: Improve message formatting and localization +semver:minor
- Modify `GAME_STATE_STARTED` message in `GameMsgs.cs` for grammatical accuracy and clarity regarding the number of traitors.
- Add new translation entries for "AN_RED_ELEPHANT" and "AN_RED_BALL" in `Test/lang/en.yml`.
- Update `Game/lang/en.yml` to use variable placeholders for role messages.
- Expand locale message templates by adding new constants in `Test/Locale/TestMsgs.cs`.
- Implement additional localization and formatting tests in `LocaleTest.cs`.
- Enhance `RoundBasedGameTest.cs` with tests for role messages, game start scenarios, and end conditions.
- Improve string handling in `StringLocalizer.cs` with utility functions and updated trimming methods.
2025-08-06 18:06:38 -07:00
MSWS
8223e15cc3 Add round start role-inform message 2025-08-06 17:41:37 -07:00
Isaac
09b4c92f3c ci: Enhance changelog generation in release workflow (#35)
- Add step in release workflow to determine base tag for changelog
generation
- Modify Generate Changelog step to include base tag as input parameter
for accurate changelog creation
2025-08-06 17:33:41 -07:00
MSWS
2498dc3d6e ci: Enhance changelog generation in release workflow
- Add step in release workflow to determine base tag for changelog generation
- Modify Generate Changelog step to include base tag as input parameter for accurate changelog creation
2025-08-06 17:12:09 -07:00
Isaac
39a6fd4119 Improve localization and CS2-specific support, additional unit tests (#34) 2025-08-06 16:30:19 -07:00
MSWS
07042301f8 refactor: Refactor timer, services, and article logic +semver:minor
- Enhance `RoundTimerListener` by making `TerminateRoundFunc` a `readonly` static field and using `Server.NextWorldUpdate` for deferred execution.
- Update `OnRoundStart` and `OnRoundEnd` for improved timer functionality and team balance in `RoundTimerListener`.
- Change service lifecycles in `Startup` from transient to scoped for `IScheduler` and `IMsgLocalizer`.
- Simplify vowel sound logic in `StringLocalizer` using switch expressions for article determination.
- Refactor `CombatHandler` to focus on event-driven architecture and simplify damage handling.
- Remove console logging from `IGame`'s `GetAlive` method to streamline and enhance performance.
2025-08-06 16:26:31 -07:00
MSWS
e1ebc71661 Merge branch 'main' into dev 2025-08-06 16:18:26 -07:00
MSWS
7469516667 ci: Fix typo and extend label pattern +semver:patch
- Fix typo in pull request template format by correcting unbalanced braces in changelogConfig.json
- Extend `label_extractor` pattern to include more label types like `cd` and `workflow` for better categorization
2025-08-06 16:17:48 -07:00
MSWS
b1b5409828 refactor: Refactor role and round handling logic
- Simplify `RoleAssignListener` by consolidating conditional logic and updating `SetClan` method signature.
- Remove unnecessary implementation exception from `ListCommand`'s `Dispose` method.
- Clean up comments in `CS2Player`, maintaining current property logic and constructors.
- Streamline round termination logic in `RoundTimerListener` and add TODO for parameter clarification.
- Refactor multiple associated files for enhanced code readability and maintenance.
2025-08-06 15:44:27 -07:00
MSWS
53ceb0baf2 Reformat & Cleanup 2025-08-05 23:59:57 -07:00
MSWS
2f81514e11 feat: Enhance game logic and role management handling
- Update `RoundTimerListener.cs` to enhance player management and control flow, introducing new fields and refining round start and end logic.
- Refine `RoleAssignListener.cs` to adjust clan assignments based on player roles, specifically setting up for `CS2DetectiveRole`.
- Implement `GetRole` method in `IGame.cs` for role-based player retrieval and enhance `GetAlive` for detailed role logging.
- Revise `CS2Game.cs` to manage role list updates, game state transitions, and ensure main thread consistency during operations.
2025-08-05 23:39:58 -07:00
MSWS
e1ab5e45db feat: Implement article handling logic and round updates.
```
- Add new localization strings and variations in `TTT/Test/lang/en.yml` for testing scenarios.
- Remove debug-only command and enhance error logging in `TTT/CS2/CS2CommandManager.cs` for better debugging support.
- Implement player respawn and improve round ending behavior in `TTT/CS2/Listeners/RoundTimerListener.cs`.
- Add article handling support and update methods for `%an%` placeholders in `Locale/StringLocalizer.cs`.
- Expand test message capabilities with new constants and methods in `TTT/Test/Locale/TestMsgs.cs`.
- Simplify role assignment logic by removing event instantiation in `TTT/CS2/Listeners/RoleAssignListener.cs`.
- Enhance access control and fix game state transition logic in `TTT/Game/RoundBasedGame.cs`.
- Update round management with new static method and using directives in `TTT/CS2/RoundUtil.cs`.
- Modify role assignment messages for grammatical accuracy in `TTT/Game/lang/en.yml`.
- Improve round-end logic and add necessary checks in `TTT/CS2/GameHandlers/RoundEndHandler.cs`.
- Clarify role name usage in message creation in `TTT/Game/GameMsgs.cs`.
- Introduce new event handling and state checks in `TTT/CS2/CS2Game.cs`.
- Add comprehensive tests for article localization and substitution in `TTT/Test/Locale/LocaleTest.cs`.
```
2025-08-05 22:52:53 -07:00
MSWS
fbf4bc8c9f feat: Add role features and localize role messages
```
- Add `SetClan` method to `PlayerExtensions` in `PlayerExtensions.cs` for clan management
- Improve command handling and debugging in `CS2CommandManager.cs` with conditional `TestClanCommand` registration and enhanced error logging
- Fix typo in `DebugInform` output in `CS2Messenger.cs` and maintain debug method consistency
- Update role assignment logic in `RoleAssignListener.cs` for team assignment and clan setting based on roles
- Introduce localization support in role assignment messages across `en.yml`, `GameMsgs.cs`, and `RoleAssigner.cs`
```
2025-08-05 21:49:47 -07:00
MSWS
24c7104a01 refactor: Enhance logging and refine role type checks
- Add console logging for player roles in `GetAlive` methods within `IGame.cs` and enhance role type matching logic
- Comment out `CBaseEntity_TakeDamageOldFunc` hooks in `CombatHandler.cs` and add player validation check
- Simplify `GameConfig` instantiation and verify correct game start in `JoinStartTest.cs`
- Rename `ScreenMsg` method to `Message` in `RoleAssigner.cs` without affecting functionality
- Enhance console logging for debugging methods in `CS2Messenger.cs` to include message type
2025-08-05 20:36:37 -07:00
Isaac
3674b025b3 ci: Update release workflow for branch flexibility (#33)
- Reference the triggering branch during checkout in the release
workflow.
2025-08-05 11:30:46 -07:00
MSWS
41b6ac0388 ci: Update release workflow for branch flexibility
- Reference the triggering branch during checkout in the release workflow.
2025-08-05 11:28:45 -07:00
MSWS
7801feaa85 ci: Update release workflow for branch flexibility
- Reference the triggering branch during checkout in the release workflow.
2025-08-05 11:28:09 -07:00
MSWS
40dff5ef0b Re-add debug logging 2025-08-05 11:22:58 -07:00
MSWS
2531d54ba5 test: Refactor game config usage in tests +semver:patch
- Add import statement for `TTT.Game` in `JoinStartTest` to utilize new functionalities
- Introduce `GameConfig` object in `JoinStartTest` for managing configuration settings
- Modify `OnJoin_StartsGame_WhenTwoPlayersJoin` test to use `GameConfig` for countdown, improving flexibility
- Change `IScheduler` lifecycle in `Startup` from `Scoped` to `Transient` for a new instance per request
2025-08-05 11:21:45 -07:00
MSWS
6f02d3b7ea refactor: Enhance thread safety and add null handling support
```
- Enhance thread safety and state consistency in `CS2Game.cs` during game start operations by ensuring main thread execution and enforcing game state consistency.
- Improve role assignment in `RoleAssigner.cs` by clearing existing roles before assigning new ones and randomizing assignments with a shuffled list of players.
- Strengthen null handling in `EventModifiedMessenger.cs` by allowing nullable `IOnlinePlayer` parameters and ensuring actions are executed with null parameters.
- Prevent active game duplication in `CS2GameManager.cs` by adding a check and throwing an exception if a game is already active.
- Introduce asynchronous execution and better synchronization in `RoundTimerListener.cs` to handle round timings in the next world update cycle.
- Refactor `PlayerConnectionsHandler.cs` for improved dependency management by introducing dependency injection for key components.
- Change directory capitalization for consistency in `ActionTest.cs` file path.
- Enhance configurability in `PlayerJoinStarting.cs` by using a configuration value for the minimum player count to start a game.
- Add new tests in `GameTest.cs` to verify the behavior of the `GetAlive` method with various scenarios and role filters.
```
2025-08-05 11:04:57 -07:00
MSWS
b4f77e43f8 Remove unnecessary dependency on IPlayerFinder in RoleAssigner.cs and preserve optional IMessenger use
- Adjust event listener registration in `PlayerConnectionsHandler.cs` to use `OnClientConnected` and simplify function signature
- Activate previously commented-out line in `CombatHandler.cs` for proper `OnTakeDamage` unhooking in `Dispose` method
2025-08-05 10:33:04 -07:00
MSWS
fce31747a1 refactor: Refactor logging and enhance round initiation
```
- Comment out initialization of `msg` and disable debug logging in `SimpleLogger.cs` to reduce dependencies and simplify debugging.
- Add a `Start` method in `CS2Game.cs` to enhance round initiation with an optional countdown and expandability for future features.
- Adjust command execution order in `RoundTimerListener.cs` to correctly manage round win conditions during COUNTDOWN and IN_PROGRESS states.
- Implement dependency injection in `CCPlayerConverter.cs` by switching to `IServiceProvider`, deferring `IMessenger` instantiation with `Lazy<T>`.
- Remove redundant logging in `PlayerConnectionsHandler.cs` to streamline startup messages.
- Update several files to enhance logging and debugging, refactor code, and improve initialization and error handling.
```
2025-08-05 10:26:02 -07:00
MSWS
6a3c7d21bd refactor: Add debug methods and enhance logging
- Add new debugging methods in `CS2Messenger.cs` and ensure they only run in debug mode using preprocessor directives
- Simplify `SimpleLogger` initialization by removing unnecessary service calls in `RoundBasedGame.cs`
- Import `System.Diagnostics` in `EventModifiedMessenger.cs` to enable potential debugging or logging enhancements
- Enhance `CCPlayerConverter.cs` by combining lookup checks, adding null checks, and improving debug messages
- Correct parameter name case in `CS2GameManager.cs` to conform to naming conventions
- Replace `IScheduler` dependency with `IServiceProvider` in `SimpleLogger.cs` and add dependency injection for messenger and scheduler components
2025-08-05 09:44:20 -07:00
MSWS
098e43777c feat: Refactor and enhance gameplay with event-driven setup +semver:patch
- Update color coding for the "game is starting" message in `en.yml` for clarity and aesthetics
- Modify `CCPlayerConverter.cs` to include dependency on `TTT.API.Messages` and refactor constructor for `IMessenger` integration
- Revise `CS2GameManager.cs` to implement event-driven game creation using `GameInitEvent`
- Change access level of `IEventBus` and `ActiveGame` in `GameManager.cs` to protected for better inheritance support
- Enhance `PlayerJoinStarting.cs` with dependency injection and configurable start countdown
- Reinstate and improve error handling for `OnTakeDamage` in `CombatHandler.cs`
2025-08-05 09:34:54 -07:00
MSWS
01aebe12e9 Update README Locale link 2025-08-05 06:27:29 -07:00
MSWS
dfd9b4f3c7 Use markdown for licenses 2025-08-05 05:59:12 -07:00
MSWS
066b6f9fb7 Remove absolute pathing in .envrc 2025-08-05 05:03:03 -07:00
MSWS
0ffd9e3773 Update CS# and licenses 2025-08-05 05:01:01 -07:00
Isaac
294fc9d3d7 Improve messaging / logging internals 2025-08-05 02:50:45 -07:00
MSWS
b34f91219e feat: Enhance message event handling and flexibility.
- Add handling logic for `BackgroundMsg` and `ScreenMsg` in `EventModifiedMessenger.cs`, including event dispatching for player-specific messages
- Update `PlayerBackgroundMessageEvent` to accept additional arguments with a params parameter
- Introduce generic type parameter `T` for `SimpleArgsSubstitution` to enhance flexibility in handling event types
- Modify `SimpleMessageSubstitution` to be generic with a type parameter `<T>`, ensuring `T` is a subclass of `PlayerMessageEvent`
- Add support for additional parameters in `PlayerScreenMessageEvent` constructor for flexible message formatting
- Refine message event handling in `MessageModificationTest`, parameterizing test instances with specific event types
2025-08-05 02:48:06 -07:00
MSWS
f54b1942b0 refactor: Refactor message formatting and substitution logic
- Add formatting functionality to `TestMessenger` and ensure consistency across methods
- Define `SimpleMessageSubstitution` class to modify player messages, with event handling and setup for unregistration
- Refactor `MessageModificationTest` to use new substitution classes, enhance test coverage and readability
- Create `SimpleArgsSubstitution` class for modifying message arguments, and improve event handling clarity
- Enhance `EventModifiedMessenger` with new methods and helper function, improve message broadcasting flexibility
2025-08-05 02:36:35 -07:00
MSWS
eb63152f61 refactor: Enhance message handling with added flexibility +semver:minor
```
Enhance Messaging and Event Handling System

- Expand GameMsgs.cs with new message types and improved structure, including methods for game state notifications and better command organization.
- Refactor PlayerJoinStarting.cs by simplifying messaging logic for cleaner code flow.
- Capitalize configuration descriptions in CS2GameConfig.cs for consistency and readability.
- Improve RoleAssigner.cs through code refactoring, optimizing argument passing for clarity.
- Add flexibility to PlayerMessageEvent.cs by introducing additional parameters for more robust event handling.

Implement Service and Localization Adjustments

- Update EventModifiedMessenger.cs to utilize IServiceProvider, adding conditional debug capabilities and preparing for future messaging enhancements.
- Transition CS2Messenger.cs from ILogger to direct console writes, supporting formatted message delivery.
- Introduce PlayerScreenMessageEvent and PlayerBackgroundMessageEvent classes to enhance player-specific event messaging.
- Leverage localization in RoundBasedGame.cs for message delivery, replacing hardcoded values and improving internationalization support.

Minor Code Enhancements and Cleanups

- Fix method signatures and imports across various files for improved consistency and readability.
- Adjust CS2Player.cs documentation for consistent terminologies.
- Clean diagram in lang/en.yml with the addition of customizable game messages for both start and cancellation scenarios.
```
2025-08-05 02:17:58 -07:00
Isaac
accd310240 Include preleases when determining versions, miscellaneous tweaks (#30) 2025-08-04 23:32:13 -07:00
MSWS
5d49a80a4a Merge branch 'main' into dev 2025-08-04 23:29:26 -07:00
MSWS
6ad656b7b2 refactor: Refactor connection handling in PlayerConnectionsHandler
- Refine settings in `TTT.sln.DotSettings` by consolidating XML tags and maintaining code style rules.
- Document missing parameter in `GiveWeapon` method of `IInventoryManager.cs`.
- Overhaul player connection logic in `PlayerConnectionsHandler.cs` by shifting focus to disconnection, replacing outdated methods, and organizing disposals.
- Note potential crash issue in `CombatHandler.cs` with a TODO, remove `OnTakeDamage` implementation, and prepare for future documentation improvements.
- Clean up `CreateGame` method in `CS2GameManager.cs` by eliminating obsolete code for better clarity.
2025-08-04 23:28:41 -07:00
MSWS
7f5cf07aae Remove unused code 2025-08-04 23:19:00 -07:00
MSWS
ef23b5dc15 Reformat and Cleanup 2025-08-04 23:15:07 -07:00
MSWS
a0c1724184 Include preleases when determining versions 2025-08-04 21:17:12 -07:00
MSWS
810150bdd5 refactor: Refactor damage handling in player events
- Modify `ArmorRemaining` property in `PlayerDamagedEvent.cs` to allow external updates and add validation for `HpLeft` to prevent invalid health values.
- Comment out old damage hooks in `CombatHandler.cs` and replace with new `OnPlayerDeath` and `OnPlayerHurt` handlers to improve event handling and consistency.
2025-08-04 21:08:49 -07:00
MSWS
17ef99bb0c Make debugs slightly more obvious 2025-08-04 20:50:23 -07:00
MSWS
2eeea9501d Remove format tests 2025-08-04 20:38:02 -07:00
MSWS
555fbfe87a Try alternative method of generating localizer 2025-08-04 20:19:13 -07:00
MSWS
0934dc86e0 Reformat 2025-08-04 20:04:03 -07:00
MSWS
aee181e352 Add more format tests 2025-08-04 19:52:23 -07:00
MSWS
740a8c14d1 refactor: Enhance extensibility and integrate CS2 system updates
Enhance Extensibility and Update API Integrations

- Make `Roles` property and `StartRound` method virtual in `RoundBasedGame.cs` to support subclass customization.
- Add logging and improve readability in `CCPlayerConverter.cs` for player conversion processes.
- Update method parameters and usage of `Server.NextWorldUpdateAsync()` in `CS2CommandManager.cs` for API adjustments.
- Add event listener registration and enhance logging in `PlayerConnectionsHandler.cs` for better handling of player connections.
- Integrate new roles and override method logic in `CS2Game.cs` for role management enhancement.

Additional changes:
- Update `CounterStrikeSharp.API` to version `1.0.331`.
- Improve `PlayerDeathEvent.cs` by removing unnecessary dead checks and making the `Victim` property non-nullable.
- Enhance event handling and logging in `Plugin/TTT.cs` for improved module loading and listener support.
- Refactor and enhance exception handling in `CombatHandler.cs` for robustness.
- Minor updates for consistency and readability across multiple files.
2025-08-04 19:07:12 -07:00
MSWS
0a68a0f060 Merge branch 'dev' 2025-08-03 04:34:15 -07:00
Isaac
882e6e70b6 test: Add validation for event listener methods +semver:patch (#29)
```
- Introduce InvalidListeners.cs to define and test invalid event listener scenarios.
- Add validation in EventBus to ensure listeners have valid event handler methods, throwing `InvalidOperationException` if invalid.
- Extend EventBusTest with new test cases for invalid listener registration, covering cases with no methods, no parameters, and incorrect parameters.
```
2025-08-03 04:31:23 -07:00
MSWS
51a95864e1 test: Add validation for event listener methods +semver:patch
```
- Introduce InvalidListeners.cs to define and test invalid event listener scenarios.
- Add validation in EventBus to ensure listeners have valid event handler methods, throwing `InvalidOperationException` if invalid.
- Extend EventBusTest with new test cases for invalid listener registration, covering cases with no methods, no parameters, and incorrect parameters.
```
2025-08-03 04:29:32 -07:00
MSWS
15b4e1c076 ci: Add label pattern extraction to changelog config
- Add new `label_extractor` configuration in `.github/changelogConfig.json` for enhanced label categorization based on title patterns, improving automation and organization in changelog generation.
2025-08-03 04:21:21 -07:00
MSWS
47bb7c3871 ci: Revamp changelog config; update workflows +semver:minor
- Delete `changelogConfig.json` to phase out or relocate changelog configurations.
- Update `.github/workflows/release.yml` to modify the `Generate Changelog` path and introduce a new "HYBRID" mode, improving changelog generation.
- Adjust `.github/workflows/release.yml` to limit the `Create GitHub Release` step to specific branches for a more efficient release process.
- Add `.github/changelogConfig.json` to include new templates and change categorization, refining the changelog structure.
2025-08-03 04:16:46 -07:00
MSWS
77a91c72f9 Fix mv command 2025-08-03 04:02:21 -07:00
MSWS
e2f9e3cd99 ci: Configure changelog generator with json file
- Add configuration for changelog generator in release workflow
2025-08-03 03:57:59 -07:00
MSWS
5c93690ab1 ci: Update release workflow and add changelog config
- Modify the artifact download step in `.github/workflows/release.yml` to skip unpacking and change the path.
- Add a new step in `.github/workflows/release.yml` to rename the artifact by appending the GitVersion output to its name.
- Update the changelog builder action to version 5 in `.github/workflows/release.yml`.
- Adjust the file reference in the release creation step in `.github/workflows/release.yml` to use the newly renamed artifact.
- Add `changelogConfig.json` configuration file with templates and defined categories for changelog items.
- Include logic in `changelogConfig.json` to ignore labels like "wip" and "ignore" and configure sorting order and template for entries.
2025-08-03 03:57:26 -07:00
MSWS
4d7e109ccf ci: Refactor release workflow permissions configuration
- Update release workflow to allow read access to pull requests.
- Modify changelog generation step to use `with:` for token input configuration.
2025-08-03 03:44:38 -07:00
Isaac
950cfa12c8 ci: Use ACTIONS_GET_PR for changelog token retrieval (#28)
- Update token retrieval in release workflow to use `ACTIONS_GET_PR`
secret instead of `GITHUB_TOKEN`.
2025-08-03 03:41:41 -07:00
MSWS
fff14f170c ci: Use ACTIONS_GET_PR for changelog token retrieval
- Update token retrieval in release workflow to use `ACTIONS_GET_PR` secret instead of `GITHUB_TOKEN`.
2025-08-03 03:38:54 -07:00
Isaac
4f3159d9c0 Include github token into changelog generator (#27) 2025-08-03 03:26:36 -07:00
MSWS
f26096c165 Merge branch 'main' into dev 2025-08-03 03:23:35 -07:00
MSWS
4b3fc19a8c Merge branch 'main' of github.com:MSWS/TTT 2025-08-03 03:23:27 -07:00
MSWS
9aa0b13e23 ci: Update release workflow for consistency and clarity
- Adjust workflow trigger condition in `.github/workflows/release.yml` to require a successful previous run.
- Update syntax for branch extraction using GitHub Actions expression in the release workflow.
- Bump `actions/checkout` to version v4.
- Modify GitVersion setup and execution to use version v4.0.1.
- Introduce conditions for creating a GitHub release only from the 'main' or 'dev' branch.
- Enhance the `Create GitHub Release` step with dynamic attributes.
- Apply formatting changes for improved clarity.
2025-08-03 03:22:36 -07:00
Isaac
f1088e458f CI Fixes (#26) 2025-08-03 03:19:43 -07:00
MSWS
3c77d5fdc1 ci: Simplify release workflow and quote names
- Remove .NET setup step in release workflow to reflect changes in dependencies or build process
- Quote workflow name in "Download artifact" step for consistency and to prevent YAML parsing issues
2025-08-03 03:15:54 -07:00
MSWS
685b3c3e61 ci: Correct artifact name in release workflow
- Update artifact download step in release workflow to use 'nightly.yml' for consistency and reference correction
2025-08-03 03:13:59 -07:00
Isaac
dcb7e82796 More CI fixes 2025-08-03 03:10:44 -07:00
MSWS
43f9a81783 ci: Update workflow trigger to 'dev' branch pushes
- Update GitHub Actions workflow to trigger on pushes to 'dev' branch instead of specific path patterns
2025-08-03 03:09:15 -07:00
Isaac
d1fe0ac606 Merge branch 'main' into dev 2025-08-03 03:08:20 -07:00
MSWS
64fceac34f ci: Update release workflow for branch flexibility
- Remove branch specification in 'Download artifact' step in release workflow to allow applicability to any branch
- Update conditional logic for creating GitHub Release to check for 'main' or 'dev' branches only
2025-08-03 03:07:34 -07:00
MSWS
7d5d7d48c3 Update artifact name 2025-08-03 03:05:56 -07:00
Isaac
21dcbf0e5a Merge pull request #24 from MSWS/dev
Fix artifact downloading
2025-08-03 03:02:33 -07:00
MSWS
6eafcb8a8c ci: Trigger nightly on release.yml file changes
- Update nightly workflow to trigger on changes to release.yml file
2025-08-03 02:57:36 -07:00
MSWS
464bad701b Merge branch 'dev' of github.com:MSWS/TTT into dev 2025-08-03 02:56:25 -07:00
MSWS
defb67b2d6 ci: Update artifact download action in release workflow
- Consolidate artifact download step in release workflow by removing duplicate actions and updating to `dawidd6/action-download-artifact`
- Add parameters for branch and workflow in artifact download step for more precise fetching
- Maintain conditional branching for GitHub release creation based on the triggering branch within the workflow
2025-08-03 02:56:07 -07:00
MSWS
7101acbdbc ci: Refine artifact handling in release workflow
- Update `.github/workflows/release.yml` to add new action permissions and refine artifact handling
- Introduce step to download 'ttt-nightly' artifact using `dawidd6/action-download-artifact@v11`
- Modify execution approach in existing build artifact download step
2025-08-03 02:55:30 -07:00
MSWS
47e81268f1 ci: Update artifact download step and permissions
- Update release workflow to improve artifact download process
  - Change artifact download action to `dawidd6/action-download-artifact@v11` and configure additional settings
  - Adjust permissions to include read access for actions
  - Rename download step ID to `download-artifact` for consistency
2025-08-03 02:45:54 -07:00
Isaac
86eab269f7 Add Credit-Based Shop System and Refactor Core TTT APIs
> ## Pull Request Overview
> 
> This is a large development pull request that adds a comprehensive shop system to the TTT plugin and refactors several core components. The changes include implementing a credit-based shop system with purchasable items, updating APIs to be more flexible with nullable types, and improving the command system architecture.
> 
> Key changes:
> 
>     * Added complete shop system with credits, items, and purchase mechanics
> 
>     * Refactored storage interfaces to support nullable return types
> 
>     * Updated messaging and command systems with improved architecture
> 
>     * Enhanced weapon system with ammo management capabilities
> 
> 
> ### Reviewed Changes
> 
> Copilot reviewed 91 out of 91 changed files in this pull request and generated 5 comments.
> Show a summary per file
> File 	Description
> TTT/Shop/* 	New shop module with credit system, purchasable items, and commands
> TTT/API/Storage/* 	Updated storage interfaces to support nullable return types
> TTT/API/Messages/* 	Simplified messenger interface by removing IOnlineMessenger
> TTT/Game/Commands/* 	Added TTT command and refactored CommandManager architecture
> TTT/CS2/* 	Updated CS2-specific implementations for new APIs
> TTT/Test/* 	Updated test infrastructure for new command and storage patterns
2025-08-03 02:40:45 -07:00
MSWS
f1ddaa04d2 Apply a few copilot suggestions, fix concurrent groups again 2025-08-03 02:35:00 -07:00
Isaac
5c34dd820a Merge branch 'main' into dev 2025-08-03 02:29:40 -07:00
Isaac
70dc321f71 Merge pull request #22 from MSWS/fix/ci
ci: Update workflows for branch condition and artifact naming
2025-08-03 02:27:51 -07:00
MSWS
3f3f6cfe0a ci: Update workflows for branch condition and artifact naming
- Update `cancel-in-progress` condition in `dotnet.yml` to exclude `main` branch runs
- Rename artifact to "ttt-nightly" in `release.yml`
2025-08-03 02:25:24 -07:00
Isaac
494c332487 Merge pull request #21 from MSWS/fix/moreReleasing
Add concurrency groups and run builds if release.yml was changed
2025-08-03 02:22:45 -07:00
MSWS
fc99b52073 ci: Update workflow concurrency and push branch settings
- Update `concurrency` configuration in `dotnet.yml` to use new syntax for branch/PR name reference
- Remove explicit `main` branch from `push` event trigger in workflow
2025-08-03 02:19:15 -07:00
MSWS
fb571cb80c ci: Update GitHub workflows for triggers and concurrency
- Restrict `.github/workflows/dotnet.yml` to trigger only on pushes to the "main" branch and expand monitored paths for changes.
- Add concurrency settings to `.github/workflows/dotnet.yml` to prevent overlapping runs.
- Disable automatic cancellation of in-progress runs in `.github/workflows/release.yml`.
- Add a blank line for improved readability in `.github/workflows/nightly.yml`.
2025-08-03 02:18:06 -07:00
Isaac
cfb3cce96b Merge pull request #19 from MSWS/fix/releaseCI
Update release workflow name
2025-08-03 02:11:32 -07:00
Isaac
b788264cd8 Merge branch 'main' into fix/releaseCI 2025-08-03 02:09:55 -07:00
Isaac
00a8b0c38d Merge pull request #20 from MSWS/fix/buildCI
Run dotnet build and test on all PRs
2025-08-03 02:09:27 -07:00
MSWS
b77cf4bbec Grant r/w perms 2025-08-03 02:07:57 -07:00
MSWS
29b45f6984 Run dotnet build and test on all PRs 2025-08-03 02:04:57 -07:00
MSWS
a27a540128 Update release workflow name 2025-08-03 02:02:22 -07:00
MSWS
344ac4a41a Merge branch 'main' into dev 2025-08-03 01:56:51 -07:00
Isaac
8ec80b33d1 Merge pull request #18 from MSWS/feat/releaseCI
Add release workflow
2025-08-03 01:56:13 -07:00
MSWS
9d801de4a1 Clean up README 2025-08-03 01:50:40 -07:00
MSWS
e50558bf4d ci: Add release workflow and update badges for consistency
- Add Discord badge to README for improved accessibility to related resources
- Create new GitHub release workflow with concurrency control, versioning, changelog generation, and artifact uploads
- Update Code Coverage badge styling in dotnet workflow to consistent `for-the-badge` design
2025-08-03 01:50:31 -07:00
MSWS
6ff8988917 refactor: Refactor roles, configs, and credit system logic.
```
Refactor and enhance role configuration, credit system, and kill handling

- **TraitorRole, DetectiveRole, and InnocentRole:** Refactored role initialization to rely on a common `RoleCfg` structure, introduced a `TargetCount` property, and tidied up logic for configuration access and player assignment.
- **CS2 Specific Roles and GameConfig:** Added custom CS2 versions of roles (e.g., CS2TraitorRole, CS2InnocentRole) with color-coded names and introduced refined configuration handling in CS2GameConfig, including improved role and round-related setups.
- **PlayerDeathEvent and Kill Handling:** Standardized player type enforcement in `PlayerDeathEvent` and added a new `PlayerKillListener` to handle credits and assists through `ShopConfig` with localized messaging.
- **Shop and Messaging System:** Enhanced the shop system by adding balance management functionality, credit multipliers, and localization support for credit-related interactions.
- **RatioBasedRole and RoleAssigner:** Refactored ratio-based role logic by replacing parameters with a `TargetCount` property and simplifying role assignment logic for clarity.
```
2025-08-02 21:40:11 -07:00
Isaac
804bd53872 Merge pull request #17 from MSWS/feat/shop
Feat/shop
2025-08-02 18:53:39 -07:00
MSWS
83f126a90b Merge branch 'feat/shop' of github.com:MSWS/TTT into feat/shop 2025-08-02 18:51:51 -07:00
MSWS
f4339ed02c Resolve copilot issues 2025-08-02 18:51:39 -07:00
Isaac
1110b2e63d Update TTT/Game/EventModifiedMessenger.cs
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
2025-08-02 18:45:11 -07:00
MSWS
b1d4536f55 feat: Refactor Deagle localization and add ShopCommand behavior
- Add `ShopCommand` behavior to `ShopServiceCollection`
- Update localization keys in `OneShotDeagle` to use `DeagleMsgs` instead of `ShopMsgs`
- Modify `ShopCommand` to register with `ICommandManager` and add required `using` directive
- Remove obsolete declarations for deagle messages in `ShopMsgs`
- Introduce `DeagleMsgs` class for managing deagle-related message creation
2025-08-02 18:42:16 -07:00
MSWS
340d2bb8e9 Refactor CommandInfo to include CallingPlayer purely 2025-08-02 18:21:34 -07:00
MSWS
5a28499d43 feat: Refactor game initialization and localization systems
```
Refactor and enhance TTT game logic, localization, and service structure

- Add `CMD_TTT` method in `GameMsgs.cs` to generate a version message; fix missing newline.
- Introduce new `CS2GameManager` class that customizes role list in `CreateGame`.
- Update `CS2ServiceCollection.cs` for dependency injection of `CS2GameManager` and restructure comments.
- Improve localization in `en.yml` with color-coded `PREFIX` and new `CMD_TTT` entry.
- Refactor `TTTCommand.cs` to use `IMsgLocalizer` for localization, replacing `IMessenger`.
- Modify `GameManager.cs` to use an `IServiceProvider` field and mark `CreateGame` as `virtual`.
- Remove `GameInitRoleListener.cs` and update role initialization logic to `CS2GameManager`.
- Adjust `GameServiceCollection.cs` by removing scoped `IGameManager` registration.
```
2025-08-02 18:01:34 -07:00
MSWS
e9ab6c591e Cleanup ShopConfig 2025-08-02 17:45:59 -07:00
MSWS
5718cebefd Reformat & Cleanup 2025-08-02 17:36:19 -07:00
MSWS
38ce3cbd51 refactor: Refactor service and messaging logic across modules
- **Cleaned up unused directives** in `GameServiceCollection.cs` by removing unused alias and using statements.
- **Improved plugin filtering** in `TTT.cs` to exclude `IPluginModule` instances when fetching `ITerrorModule` implementations.
- **Enhanced command injection logic** in `CS2CommandInfo.cs` by leveraging `IServiceProvider` for dependability and updating messaging handling with `IMessenger`.
- **Refactored and improved error handling** in `CS2CommandManager.cs`, including better error logging and updates to `ReplySync` logic with localized messaging.
- **Added a new generic error message** with placeholders for dynamic error details in `GameMsgs.cs` and updated the English language file `lang/en.yml`.

Other minor changes:
- Updated field visibility in `CommandManager.cs` for consistency.
- Added a comment to disable a namespace check in `WeaponType.cs`.
2025-08-02 17:35:11 -07:00
MSWS
4941f02f4b Change plugin to be named TTT.dll 2025-08-02 02:25:46 -07:00
MSWS
a84ff05597 Merge branch 'dev' into feat/shop 2025-08-02 02:22:01 -07:00
MSWS
fff07504db refactor: Get basic command output working with CS2
```
Refactor messaging system and improve modularity across TTT framework

- Updated `ServiceCollectionExtensions` to include a new overloaded method for plugin behavior registration, improving the modularity and reusability of extension types.
- Renamed `TTTCommand.cs` to a new directory structure, replaced `IOnlineMessenger` with `IMessenger`, and updated messaging to include TTT version information.
- Renamed and adjusted fields, logic, and dependency registrations in `CS2CommandManager`, aligning with the new command and messenger system.

Other notable changes:
- Updated `CS2GameConfig` traitor health defaults from 1000 to 100, with a new valid range.
- Cleaned unused imports and updated registration methods for various services, such as `CS2ServiceCollection` and `GameServiceCollection`.
- Improved documentation and comments for clarity while removing unnecessary or outdated elements.
```
2025-08-02 02:17:57 -07:00
MSWS
eb083fe735 feat: Add TTTCommand and enhance command/message handling
- Register new `TTTCommand` in `CS2CommandManager` and adjust command processing flow
- Create `TTTCommand` class with dependency injection, command properties, and stubbed logic
- Update `IOnlineMessenger` to support nullable players and improve type handling logic
- Modify `CS2ServiceCollection` to use `AddPluginBehavior` for `CS2CommandManager` initialization
2025-08-02 00:52:39 -07:00
MSWS
0cfff80b7f feat: Add subcommand system and improve shop command structure
- Add support for the "list" subcommand in `ShopCommand` with proper dependency setup and subcommand initialization
- Make `player` parameter nullable in `IMessenger.Message` and add nullability support
- Add `ListCommand` implementation to list shop items, utilizing dependency injection and adhering to the `ICommand` interface
- Refactor `creditsForKillCache` to `creditsForKillDictionary` in `ShopConfig` for improved naming clarity and cleaner dictionary initialization
2025-08-02 00:13:48 -07:00
MSWS
3b304cba8c feat: Refactor weapon system to use IWeapon interface.
```
Refactor and update TTT weapon, role, and shop systems

- Add `OneShotDeagle` class implementing `IWeapon` and `IShopItem` with dependency injection and localized messages.
- Replace the deprecated `GiveWeapon` method across roles (`DetectiveRole`, `TraitorRole`, `InnocentRole`) to wrap weapons in `BaseWeapon` objects.
- Create `BaseWeapon` class and `IWeapon` interface, standardizing weapon properties such as `Id`, `ReserveAmmo`, and `CurrentAmmo`.
- Refactor inventory systems (`IInventoryManager`, `CS2InventoryManager`, `FakeInventoryManager`) to accept `IWeapon` instead of string `weaponId` and add overloads for handling weapon removal.
- Restructure shop files, adding `ShopConfig` for role-related credit management and renaming/moving configurations (`ShopItemConfig` and `IShopItem`).

Additional changes:
- Update project metadata in `Shop.csproj` to target framework net8.0 and remove redundant references.
- Add `PlayerExtensions` static class to streamline weapon retrieval through LINQ and validation.
```
2025-08-02 00:02:04 -07:00
MSWS
1befb39507 feat: Implement spectator role and refactor role assignment logic
```
- Introduce `SpectatorRole` into game and replace outdated `SpectatorRole` implementation with a new version in `CS2/SpectatorRole.cs`.
- Add dependency injection for improved modularity across several files, including `RoleAssignListener.cs`, `GameManager.cs`, and `GameInitRoleListener.cs`.
- Refactor `ShopConfig.cs` to use a dictionary-based kill credit cache for optimized role-based credit retrieval.
- Update `RoundBasedGame.cs` to use a public `Roles` property and ensure fallback to default `GameConfig` values if null.
- Add new game events, including `GameInitEvent.cs` to enable customization of initialization logic.

- Minor improvements include organizing imports, adding missing newlines, cleaning up unused directives, and refining code structure in several files for better readability and maintainability.
```
2025-08-01 16:13:13 -07:00
MSWS
6ae0f29b03 Fix double-embedding of zip 2025-08-01 15:41:15 -07:00
MSWS
b20c0c2f66 feat: Refactor and expand shop system with storage and commands
```
Refactor and expand shop and storage functionality

- Update `IKeyedStorage` interface to add a `Load` method and remove `IStorage` inheritance.
- Introduce `OneShotDeagle` shop item class and configuration with placeholders for logic.
- Add new `Shop` class with player balance management, item registration, and a stubbed `TryPurchase` method.
- Implement `ShopConfig` for role-based credit logic and default credits for player actions.
- Add `PurchaseResult` enum to define outcomes of purchase operations.
- Relocate and restructure shop-related files, updating namespaces, directory structure, and references.
- Add localization support for shop items with the new `lang/en.yml` file.
- Refactor `IWriteable` and related storage interfaces, adjusting methods for clarity and functionality.
- Introduce tools like `ShopCommand`, `RoundBalanceClearer`, and `ShopMsgs` to support shop extensibility and cleanup.
- Harmonize event priority constants in `EventHandlerAttribute` for improved clarity.
```
2025-08-01 14:57:21 -07:00
MSWS
7246089859 Start work on shop 2025-08-01 13:47:01 -07:00
MSWS
883a211db5 refactor: Refactor and clean up game logic and role assignment
- Refactor `GameEndLogsListener` to replace direct instantiation of `finder` and `messenger` with static/inherited members, and simplify `OnGameEnd` logic for better clarity.
- Improve `RoleAssigner` by changing `players` parameter to `HashSet` for mutability, handling canceled events to prevent reprocessing, and enhancing role assignment error handling.
- Clean up `DetectiveRole` by removing redundant nullable `IMsgLocalizer` and referencing a globally scoped `Localizer` for consistency.
- Update `GameRestartListener` to remove direct `IGameManager` instantiation and standardize property references to align with new conventions.
- Enhance `RoundTimerListener` in CS2 to include `CounterStrikeSharp.API`, update round state commands, and refine conditional logic.
2025-08-01 13:23:33 -07:00
MSWS
5993fe0b5a refactor: Refactor role assignment logic into helper method
- Refactor `RoleAssigner` to extract role assignment logic into `tryAssignRole` helper method for improved readability and modularity
- Simplify role assignment loop by replacing `roleAssigned` flag with `tryAssignRole` return value
- Enhance variable naming for clarity and fix inefficiencies in role processing logic
- Improve code organization and reduce complexity of `AssignRoles` method
2025-08-01 13:01:19 -07:00
Isaac
277063beb0 Merge pull request #16 from MSWS/license
Add license and contributing.md
2025-08-01 05:18:10 -07:00
MSWS
4af22a85c9 Add license and contributing.md 2025-08-01 05:09:20 -07:00
MSWS
a356dea18b Update licenses 2025-08-01 04:28:36 -07:00
Isaac
081aadebb6 Merge pull request #15 from MSWS/MSWS-patch-1
Create dependabot.yml
2025-08-01 04:21:27 -07:00
Isaac
bd7104d79d Create dependabot.yml 2025-08-01 04:19:48 -07:00
MSWS
f3d0840563 Try fix empty version 2025-08-01 03:58:26 -07:00
MSWS
4cd5865381 Just label github output with version 2025-08-01 03:56:11 -07:00
MSWS
97ff684059 Force Nightly build 2025-08-01 03:45:05 -07:00
MSWS
984a235abb refactor: Refactor unused params, add GitVersion, and improve CI
- Update `OnTestEvent` and `AfterOnEvent` methods to use unused variable naming conventions for clarity (`SingleEventListener.cs` and `CancelableEventListener.cs`)
- Add GitVersion integration and improve artifact handling in `.github/workflows/nightly.yml`
- Refactor `CommandManagerTests` constructor for cleaner primary constructor usage
2025-08-01 03:43:18 -07:00
Isaac
bf1a32988e Merge pull request #14 from MSWS/dev
Refactor Game Event Handling and Build Configuration; Improve Listener Architecture and Test Coverage
2025-08-01 03:23:45 -07:00
MSWS
ead89fbba5 build: Optimize build config and improve logging transparency
- Add conditional exclusion for test language files in `Release` builds in `Locale.csproj`
- Simplify `dotnet` commands in GitHub Actions workflow
2025-08-01 02:57:06 -07:00
MSWS
d7a20a75c5 Restore before build 2025-08-01 02:45:20 -07:00
MSWS
a9c332b914 Add Listener-specific registration, include locales in nightly build 2025-08-01 02:44:17 -07:00
MSWS
e4ec9aa7a1 Add JetBrains Annotations, reformat 2025-08-01 02:28:38 -07:00
MSWS
ccb840ebb4 refactor: Refactor code for consistency, readability, and cleanup
```
- Remove unused namespace imports across multiple files to clean up code.
- Reorganize constructors, fields, and method orders for improved readability and consistency in various classes, including `RoundBasedGame`, `PlayerActionsTest`, and `GameTest`.
- Change expression-bodied methods to block-bodied methods in `EndReason`, `IGameManager`, and other API classes for consistency.
- Add, remove, or adjust newlines and braces to improve code structure and maintainability.
- Refactor `CombatHandler` to introduce memory module imports, update event dispatch logic, and improve damage-handling workflows.
```
2025-07-31 22:11:31 -07:00
MSWS
bf1daf374b Resolve compiler warning 2025-07-31 21:40:41 -07:00
MSWS
20b849fb0c refactor: Refactor and extend game round and event handling logic
```
- Add `GameRestartListener` class to handle game restarts upon end events
- Add `GameRestartingTest` to verify `GameRestartListener` functionality, including game state transitions after errors
- Refactor `PlayerActionsTest` for consistency, readability, and inheritance from `GameTest`
- Update `EndReason` constructors to simplify initialization and add overloads for improved flexibility
- Rename and refactor multiple CS2 classes (e.g., `RoundStartTimerListener`, `CombatListeners`, `PlayerListeners`) to align with updated naming conventions and broaden functionality

- Improve balance and configuration settings, including time-between-rounds support in `GameConfig` and `CS2GameConfig`
- Add `RoundEndHandler` to handle game conclusion logic and integrate with dependency injection

- Introduce `GameTest` utility class to streamline test setup and dependency management
- Apply cleanups and naming normalization across multiple files for code consistency and maintainability
```
2025-07-31 21:38:37 -07:00
MSWS
2433476585 refactor: Refactor and expand game listener and test coverage
```
Refactor and enhance game listeners and tests

- Rename `GameEndListener` to `PlayerCausesEndListener` in `GameEndListener.cs` and updated corresponding references.
- Update `RoundEndingTest.cs` to reflect the new `PlayerCausesEndListener` changes, ensuring consistency and adjusting tests for game-ending events.
- Add new test file `PlayerActionsTest.cs` to validate player-related events such as kills, damage, and role assignments, with dependency injection and comprehensive test cases.
- Rename `PlayerJoinBaseStartListener` to `PlayerJoinStarting` in `JoinStartTest.cs` and update related object instantiations.
- Introduce new `GameEndLogsListener` class to handle game-end logging, utilizing dependency injection and sending formatted log messages to players.
```
2025-07-31 20:54:59 -07:00
MSWS
11b78fa378 Update GamePlayerActionsListener to inherit from Base 2025-07-31 20:11:57 -07:00
Isaac
97cdf16f59 Merge pull request #13 from MSWS/feat/cs2Config
Introduce logging, actions, and updated listeners
2025-07-31 20:05:26 -07:00
MSWS
0077ec42ac Merge branch 'feat/cs2Config' of github.com:MSWS/TTT into feat/cs2Config 2025-07-31 19:21:01 -07:00
MSWS
d1bf0950f0 feat: Introduce logging, actions, and updated listeners
```
- Add `GamePlayerActionsListener` to manage player event handling and game actions
- Update `PlayerDamagedEvent` constructor to support fall damage and nullable weapon values
- Introduce `SimpleLogger` and `IActionLogger` for improved action logging capabilities
- Replace `PlayerDeathListener` with `GameEndListener` in tests and rename relevant files
- Add utility classes and extensions (`ServerExtensions`, `RoundUtil`, `RoundStartTimerListener`) for round and server management
```
2025-07-31 19:20:55 -07:00
MSWS
e93b0290e4 feat: Introduce logging, actions, and updated listeners
```
- Add `GamePlayerActionsListener` to manage player event handling and game actions
- Update `PlayerDamagedEvent` constructor to support fall damage and nullable weapon values
- Introduce `SimpleLogger` and `IActionLogger` for improved action logging capabilities
- Replace `PlayerDeathListener` with `GameEndListener` in tests and rename relevant files
- Add utility classes and extensions (`ServerExtensions`, `RoundUtil`, `RoundStartTimerListener`) for round and server management
```
2025-07-31 19:19:47 -07:00
Isaac
c7c2b3e09b Merge pull request #12 from MSWS/feat/cs2Config
Flesh out cs2 config
2025-07-31 17:12:18 -07:00
MSWS
e382d2195e refactor: Refactor game ending logic to use WinningRole concept
- Update `RoundBasedGame` logic to replace `WinningTeam` with `WinningRole` for clarity and consistency.
- Refactor `PlayerDeathListener` to handle draw scenarios with `EndReason` and improve winning role determination logic.
- Rename and enhance `EndReason` in the API to better handle game-ending scenarios, including updated constructors and initialization methods.
2025-07-31 17:09:12 -07:00
Isaac
19548b774d Merge branch 'main' into feat/cs2Config 2025-07-31 16:53:47 -07:00
MSWS
41bba21f9b Flesh out cs2 config 2025-07-31 16:52:19 -07:00
Isaac
a7eb5cadde Merge pull request #11 from MSWS/ms/dev
refactor: Refactor command execution checks with switch statement
2025-07-31 16:19:52 -07:00
Isaac
1707451e72 Merge pull request #8 from MSWS/feat/gameLogic
Game Logic
2025-07-31 16:19:17 -07:00
Isaac
af95f94692 Merge pull request #10 from MSWS/documentation/Locale
Flesh out readmes
2025-07-31 16:07:38 -07:00
Isaac
d78de2dd78 Merge pull request #9 from MSWS/overhaul/LocaleProgram
Overhaul LocaleProgram
2025-07-31 16:06:12 -07:00
MSWS
d8a742b413 Format 2025-07-31 16:05:27 -07:00
MSWS
029cc420a8 Overhaul LocaleProgram 2025-07-31 16:02:48 -07:00
MSWS
85626af7c7 Flesh out readmes 2025-07-31 15:59:26 -07:00
MSWS
7ccc8e886a Add more unit tests for team logic 2025-07-31 15:50:37 -07:00
MSWS
1655287ea7 refactor: Refactor command execution checks with switch statement
Refactor `CommandManager` to use a switch statement for conditional checks, improving readability and structure.
2025-07-31 15:33:29 -07:00
MSWS
02898baac1 Merge branch 'main' into feat/gameLogic 2025-07-31 15:29:22 -07:00
MSWS
5709927810 Reformat & Cleanup 2025-07-31 15:24:50 -07:00
MSWS
707b7082b4 More merge resolultions 2025-07-31 15:03:33 -07:00
MSWS
626b877905 refactor: Refactor player APIs and improve game event handling
```
Refactor player and game handling logic; improve event system robustness

- **CS2PlayerFinder.cs**: Updated return types for `AddPlayer` and `RemovePlayer` methods to ensure consistency with the updated player interfaces; added missing newline.
- **IPlayerFinder.cs**: Adjusted method return types for `AddPlayer` and `RemovePlayer` to match new API requirements.
- **EventBus.cs**: Added detailed exceptions for invalid listener signatures; fixed parameter handling in `Dispatch` to use array-based invocation.
- **TestPlayer.cs**: Removed unused `weapons` collection and methods; dropped constructor and placeholders for unused features.
- **FakePlayerFinder.cs**: Updated `AddPlayer` and `RemovePlayer` methods to include return statements and adjusted their return types.

- Introduced new game logic and event listeners:
  - **IGameManager.cs**: Added `IsGameActive` method to verify ongoing game status.
  - **PlayerDeathListener.cs**: Utilized `IsGameActive()` for game activity checks and added new `OnLeave` handler for `PlayerLeaveEvent`.
  - **PlayerDiesOnLeaveListener.cs**: Implemented new listener to handle player departures by marking them not alive and dispatching corresponding death events.
  - **PlayerDeathEvent.cs**: Refactored class structure with added validation for dead players and improved argument validation in its constructor.

- Enhanced and added new tests:
  - **DeathListenerTest.cs**: Added new test class to verify game end behavior via `PlayerDeathEvent`. Simulated player death scenarios and tested event handling.
  - **RoundBasedGameTest.cs**: Simplified test logic by reworking constructors, consolidating dependencies, and updating method calls to follow API changes.
```
2025-07-31 15:02:08 -07:00
MSWS
fe99fb0be3 refactor: Refactor game listeners and enhance player state handling
```
Refactor game listeners and improve player state management

- Add `PlayerJoinBaseStartListener` to handle game start logic, replacing `PlayerJoinGameStartListener`.
  - Prevent game start if one is already active and ensure at least 2 players are online.
  - Notify players of game start and initialize the game with a delay.
- Replace `PlayerJoinGameStartListener` with a streamlined implementation and delete the outdated class.
- Introduce `PlayerDeathListener` to manage game-ending logic based on alive players and winning roles.
- Update `IGame` interface:
  - Rename `winningTeam` to `winningRole` in the `EndGame` method.
  - Add `GetAlive` methods for player queries, including role-based filtering.
- Add abstract `BaseListener` class to centralize dependency handling and lifecycle management for listeners.
- Simplify `JoinStartTest` by removing unused dependencies and updating tests to reflect listener changes.
```
2025-07-31 15:01:54 -07:00
Isaac
94c8c42274 Merge pull request #5 from MSWS/feat/commands
Command Manager
2025-07-31 14:58:32 -07:00
MSWS
a9d081d1ee Implement FakePermissionManager 2025-07-31 14:56:46 -07:00
MSWS
2d4fb0928b refactor: Refactor command execution and permission management
```
Refactor command execution logic and update permission handling

- Add `CanExecute` method to `ICommandManager` for permission validation of commands.
- Remove `CanExecute` method from `ICommand` to shift permission validation responsibility.
- Update `CS2PermManager` implementation to use generic player types for `HasFlags` and `InGroups` methods.
- Refactor `IPermissionManager` to remove generics and explicitly use `IPlayer` type.
- Update `CommandManager` to use dependency injection for `IPermissionManager` and refactor logic to integrate the new `CanExecute` method.
```
2025-07-31 14:52:51 -07:00
MSWS
9811c5d11d More merge resolution 2025-07-31 14:43:17 -07:00
MSWS
e2a5c3fd2f Rebase main 2025-07-31 14:42:05 -07:00
Isaac
e7736693d3 Merge branch 'main' into feat/commands 2025-07-31 14:39:18 -07:00
Isaac
28268ea9e6 Overhaul/player wrapper (#7)
* Add Admin Data

* Create Command Result Enum

* Prep For Tests

* add TODO

* implement commandinfo

* create command interface

* gAdd Admin Data

# Conflicts:
#	TTT/CS2/CS2Player.cs

* Create Command Result Enum

* Prep For Tests

* add TODO

* implement commandinfo

* create command interface

* Refactor out inventory and permission to their own interfaces

* Resolve reverse group perm check

---------

Co-authored-by: ShookEagle <shookeagle@gmail.com>
2025-07-31 14:37:39 -07:00
Isaac
f01b491f8b Refactor out inventory and permission to their own interfaces (#6)
* Refactor out inventory and permission to their own interfaces

* Resolve reverse group perm check
2025-07-31 14:28:26 -07:00
MSWS
36b74bb8f8 refactor: Refactor player APIs and improve game event handling
```
Refactor player and game handling logic; improve event system robustness

- **CS2PlayerFinder.cs**: Updated return types for `AddPlayer` and `RemovePlayer` methods to ensure consistency with the updated player interfaces; added missing newline.
- **IPlayerFinder.cs**: Adjusted method return types for `AddPlayer` and `RemovePlayer` to match new API requirements.
- **EventBus.cs**: Added detailed exceptions for invalid listener signatures; fixed parameter handling in `Dispatch` to use array-based invocation.
- **TestPlayer.cs**: Removed unused `weapons` collection and methods; dropped constructor and placeholders for unused features.
- **FakePlayerFinder.cs**: Updated `AddPlayer` and `RemovePlayer` methods to include return statements and adjusted their return types.

- Introduced new game logic and event listeners:
  - **IGameManager.cs**: Added `IsGameActive` method to verify ongoing game status.
  - **PlayerDeathListener.cs**: Utilized `IsGameActive()` for game activity checks and added new `OnLeave` handler for `PlayerLeaveEvent`.
  - **PlayerDiesOnLeaveListener.cs**: Implemented new listener to handle player departures by marking them not alive and dispatching corresponding death events.
  - **PlayerDeathEvent.cs**: Refactored class structure with added validation for dead players and improved argument validation in its constructor.

- Enhanced and added new tests:
  - **DeathListenerTest.cs**: Added new test class to verify game end behavior via `PlayerDeathEvent`. Simulated player death scenarios and tested event handling.
  - **RoundBasedGameTest.cs**: Simplified test logic by reworking constructors, consolidating dependencies, and updating method calls to follow API changes.
```
2025-07-31 14:14:33 -07:00
ShookEagle
94218f819c Fix Tests 2025-07-31 11:03:04 -05:00
ShookEagle
af7d267748 Remove unused class 2025-07-31 10:55:34 -05:00
ShookEagle
8746b89d3b Implement FakeLocalizer.cs 2025-07-31 10:52:32 -05:00
ShookEagle
439d3fd84e Collect Services 2025-07-31 09:22:24 -05:00
ShookEagle
bb58d89a95 Unit Test Command Manager 2025-07-31 09:22:17 -05:00
ShookEagle
4008574418 Build Command Manager 2025-07-31 09:22:05 -05:00
ShookEagle
a2613bc96f Add ArgCount 2025-07-31 09:21:52 -05:00
ShookEagle
12acca0427 Create ICommand interface 2025-07-31 09:16:47 -05:00
ShookEagle
8efd5efc10 Update Player Tests 2025-07-31 09:16:27 -05:00
ShookEagle
153b82a3ad Add Command Locales 2025-07-31 09:16:17 -05:00
Reece
c2b6b1aceb Merge pull request #4 from MSWS/feat/commands-update
Feat/commands update
2025-07-31 07:30:25 -05:00
MSWS
a56d2bf8de refactor: Refactor game listeners and enhance player state handling
```
Refactor game listeners and improve player state management

- Add `PlayerJoinBaseStartListener` to handle game start logic, replacing `PlayerJoinGameStartListener`.
  - Prevent game start if one is already active and ensure at least 2 players are online.
  - Notify players of game start and initialize the game with a delay.
- Replace `PlayerJoinGameStartListener` with a streamlined implementation and delete the outdated class.
- Introduce `PlayerDeathListener` to manage game-ending logic based on alive players and winning roles.
- Update `IGame` interface:
  - Rename `winningTeam` to `winningRole` in the `EndGame` method.
  - Add `GetAlive` methods for player queries, including role-based filtering.
- Add abstract `BaseListener` class to centralize dependency handling and lifecycle management for listeners.
- Simplify `JoinStartTest` by removing unused dependencies and updating tests to reflect listener changes.
```
2025-07-30 22:33:36 -07:00
MSWS
040e035717 Refactor out inventory and permission to their own interfaces 2025-07-30 22:02:12 -07:00
MSWS
c20ee525ff Merge branch 'feat/commands-update' of github.com:MSWS/TTT into feat/commands-update 2025-07-30 21:23:34 -07:00
ShookEagle
e0452a0409 create command interface 2025-07-30 21:23:27 -07:00
ShookEagle
f4929f41b9 implement commandinfo 2025-07-30 21:23:27 -07:00
ShookEagle
f76137ab1d add TODO 2025-07-30 21:23:27 -07:00
ShookEagle
88d72c4e21 Prep For Tests 2025-07-30 21:23:27 -07:00
ShookEagle
de89168bfd Create Command Result Enum 2025-07-30 21:23:27 -07:00
ShookEagle
38352aa80c gAdd Admin Data
# Conflicts:
#	TTT/CS2/CS2Player.cs
2025-07-30 21:23:24 -07:00
Isaac
b1076981a3 Ms/dev (#3)
* Overhaul locale structure

* Reformat & Cleanup

* refactor: Refactor roles to use dependency injection.

```
Introduce dependency injection and refactor role architecture

- Refactor `RoleAssignerTest` to use `IServiceProvider` for dependency injection, update role initialization, and align test cases accordingly.
- Update `IOnlinePlayer` and `IGame` interfaces to use the fully qualified namespace for roles and modify method signatures to reflect new role architecture.
- Add `BaseRole` abstract class and refactor role classes (e.g., `InnocentRole`, `DetectiveRole`, `TraitorRole`, `RatioBasedRole`) to inherit from it, implementing dependency injection and overriding key properties and methods.
- Introduce new storage interfaces (`IStorage<T>`, `IWriteable<T>`, `IKeyedStorage<T>`) for improved configuration management and add related test implementations (e.g., `FakeConfig`, `MemoryStorage`).
- Add `GameConfig` class for configurable game and round settings, implement `CS2GameConfig` class to manage configuration storage and plugin module lifecycle, and refactor `RoundBasedGame` to leverage the new configuration structure.
```

* Fix lang copying

* Rename step

* Add debug

* Fix path

* refactor: Refactor roles and role assignment for consistency.

```
Refactor roles and role assignment logic for improved consistency and dependency management

- Refactor `DetectiveRole` to replace `localizer` with `Localizer` property, implement `OnAssign` for player configuration, and improve overall consistency.
- Update `RoleAssigner` to use `IServiceProvider` for dependency injection and call `OnAssign` during role assignment.
- Simplify `RoundBasedGame` constructor and remove redundant fields, improving initialization and readability.
- Adjust `TraitorRole` to use the refactored `Localizer` property, override `OnAssign`, and streamline weapon assignment logic.
- Refactor `BaseRole` to support dependency injection via new protected fields and updated initializations.

Additional: Improved unit tests for `RoleAssigner` and updated `InnocentRole` to align with new role assignment structure.
```

* Reformat and Cleanup
2025-07-30 21:19:12 -07:00
Isaac
c51f85ffd3 Update locale structure, begin config API (#2)
* Overhaul locale structure

* Reformat & Cleanup

* refactor: Refactor roles to use dependency injection.

```
Introduce dependency injection and refactor role architecture

- Refactor `RoleAssignerTest` to use `IServiceProvider` for dependency injection, update role initialization, and align test cases accordingly.
- Update `IOnlinePlayer` and `IGame` interfaces to use the fully qualified namespace for roles and modify method signatures to reflect new role architecture.
- Add `BaseRole` abstract class and refactor role classes (e.g., `InnocentRole`, `DetectiveRole`, `TraitorRole`, `RatioBasedRole`) to inherit from it, implementing dependency injection and overriding key properties and methods.
- Introduce new storage interfaces (`IStorage<T>`, `IWriteable<T>`, `IKeyedStorage<T>`) for improved configuration management and add related test implementations (e.g., `FakeConfig`, `MemoryStorage`).
- Add `GameConfig` class for configurable game and round settings, implement `CS2GameConfig` class to manage configuration storage and plugin module lifecycle, and refactor `RoundBasedGame` to leverage the new configuration structure.
```

* Fix lang copying

* Rename step

* Add debug

* Fix path
2025-07-30 20:10:40 -07:00
ShookEagle
33c0ce5d9a create command interface 2025-07-30 18:27:22 -05:00
ShookEagle
654333c883 implement commandinfo 2025-07-30 18:27:13 -05:00
ShookEagle
dd4291c5d5 add TODO 2025-07-30 18:27:03 -05:00
ShookEagle
9b6c027ce5 Prep For Tests 2025-07-30 18:26:31 -05:00
ShookEagle
93164d9436 Create Command Result Enum 2025-07-30 18:23:40 -05:00
ShookEagle
dadc4a1c2f Add Admin Data 2025-07-30 18:23:27 -05:00
Isaac
8eb09b27e8 Add more locale tests and licenses (#1)
* More localization, add MIT License

* Add all licenses

* Finish up locale tests for now

* Run dotnet on all branches
2025-07-30 16:21:31 -07:00
MSWS
942b46ba72 Add more localization tests 2025-07-30 06:55:50 -07:00
MSWS
9a66dbccf9 Fix compiler warning and Versioning Namespace 2025-07-30 06:08:00 -07:00
MSWS
b44c73cf87 feat: Add IMsgLocalizer and improve localization support
```
Introduce IMsgLocalizer interface and improve localization functionality

- Extend `StringLocalizer` to support `IMsg` object localization and implement the new `IMsgLocalizer` interface.
- Update `.github/workflows/dotnet.yml` to use newer Actions versions, enable coverage tracking, and generate dynamic coverage badges.
- Add `IMsgLocalizer` interface and implement localization indexer in `IMsgLocalizer.cs`.
- Update dependency injection in `Startup.cs` to register `IMsgLocalizer` and refine localization services.
- Improve tests in `LocaleTest.cs` to validate `IMsgLocalizer` usage, placeholder substitution, and remove redundant assertions.

Minor: Adjust `en.yml` formatting by removing unnecessary quotes.
```
2025-07-30 03:59:53 -07:00
MSWS
aa37d6e78a ci: Add step to copy "lang" folder in build output
- Update .NET GitHub Actions workflow to include step for copying "lang" folder to build output directory
2025-07-30 03:41:48 -07:00
MSWS
7d71bcc72e Fix OS specific path again 2025-07-30 03:38:00 -07:00
MSWS
ffc09cc3f4 Add Localization 2025-07-30 03:32:31 -07:00
MSWS
642745b156 refactor: Refactor namespaces, interfaces, and game logic
```
Refactor namespaces, improve naming consistency, and enhance game and role functionality

- **JoinMessageTest.cs**: Updated to use `IPlayerFinder` and fixed method casing.
- **CS2Player.cs and CCPlayerConverter.cs**: Added new `using` directives, introduced nullable checks, and implemented `GetPlayer` functionality in `CCPlayerConverter`.
- **RoundBasedGame.cs**: Renamed methods, improved game state handling, and added `EndGame` and `Dispose` methods.
- **CS2/CS2PlayerFinder.cs**: Added a new class implementing `IPlayerFinder` with methods utilizing `TTT.API.Player`.
- **Test/Game/Roles/RoleAssignerTest.cs**: Refactored to use a new `TestRoles` structure and added a cancellation-based test for role assignment.
- Moved and renamed multiple files (e.g., `IRoleAssigner`, `IGame`, `IGameManager`) to align with updated directory structure.
- Newly created files include `RoleAssignListener`, `RoleAssignCanceler`, and `TestRoles`.

Miscellaneous:
- Changed various method names to follow PascalCase conventions (e.g., `addPlayer` to `AddPlayer`).
- Streamlined imports across multiple files to align with updated namespaces and dependencies.
- Removed and relocated legacy files (`Channel.cs`) to clean up outdated definitions.
```
2025-07-29 22:28:23 -07:00
MSWS
d2ffe04da4 Optimize & Cleanup 2025-07-29 21:36:02 -07:00
MSWS
511afc0dfb Add init tests 2025-07-29 21:34:44 -07:00
MSWS
f6ef176fdd ci: Update .NET workflow to use v4 and add coverage summary
- Update actions/checkout and setup-dotnet to v4 in dotnet.yml
- Target .NET 8.0.x in Setup .NET step
- Modify test execution to run Test.dll directly from build output
- Add step to write code coverage results to GitHub Job Summary
2025-07-29 20:37:32 -07:00
MSWS
2d555ec15b Have dotnet run it 2025-07-29 20:27:59 -07:00
MSWS
0a8d72053d Disable compression 2025-07-29 20:24:43 -07:00
MSWS
348ed914f1 chmod to allow executing the test 2025-07-29 20:23:30 -07:00
MSWS
00be65d9e1 Fix Test dll path 2025-07-29 20:21:13 -07:00
MSWS
ccecc714e1 Keep configuration consistent 2025-07-29 20:18:01 -07:00
MSWS
436b340ea0 Try to fix unit tests 2025-07-29 20:10:16 -07:00
MSWS
e09080253a Fix Test dir again 2025-07-29 20:06:16 -07:00
MSWS
1042dc2647 Separate test 2025-07-29 20:04:30 -07:00
MSWS
6d91642171 Begin work on optimizing build + test 2025-07-29 20:01:40 -07:00
MSWS
4145c40aa1 Add .runsettings 2025-07-29 19:53:42 -07:00
MSWS
4eb61bad05 Adjust namespaces 2025-07-29 19:19:28 -07:00
MSWS
fea28e19f6 ci: Update coverage report paths in dotnet workflow
- Update coverage output path in dotnet workflow to use environment variable
- Simplify filename for Code Coverage Summary Report configuration
2025-07-29 19:13:42 -07:00
MSWS
e4105090f8 Exclude more stuff from code coverage 2025-07-29 19:09:12 -07:00
MSWS
86756df7ce Fix unit test setup, add READMEs 2025-07-29 19:07:45 -07:00
MSWS
b4b960adda Allow publish to build instead 2025-07-29 18:37:15 -07:00
MSWS
6f6e377d3c Try explicitly stating output dir 2025-07-29 18:33:16 -07:00
MSWS
1c2f7a5bc1 Fix Plugin.csproj to reflect deeper placement 2025-07-29 18:28:04 -07:00
MSWS
d33c7ccbad ci: Simplify CI by removing GitVersion and fixing test paths
- Update `.github/workflows/dotnet.yml` to remove GitVersion step and fix test project path
- Adjust `TTT/Directory.Build.props` to exclude certain `ItemGroup` conditions during CI on non-Windows platforms
2025-07-29 18:25:11 -07:00
MSWS
2ebfa68683 Fix || -> Or 2025-07-29 18:21:20 -07:00
MSWS
c8655dc437 Try just allowing it on GitHub CI 2025-07-29 18:20:03 -07:00
MSWS
0fa508b4fb Update CI to reflect new structure 2025-07-29 18:14:05 -07:00
MSWS
31ea9ed6ae Fix path triggers again 2025-07-29 18:12:00 -07:00
MSWS
c62e008a40 Fix includes path 2025-07-29 18:10:49 -07:00
MSWS
ee6649376f Overhaul file structure 2025-07-29 18:06:37 -07:00
MSWS
10118c9123 ci: Add GitVersion steps to build and test workflows
- Add `Run GitVersion` step to build and test jobs in `.github/workflows/dotnet.yml` for version output and consistency
- Include GitVersion installation step in test job
2025-07-29 18:01:53 -07:00
MSWS
df64cd573b ci: Refactor GitVersion handling for cross-platform builds
- Remove `GenerateGitVersionInformation` target block from `Directory.Build.props` for non-Windows OS compatibility.
- Add GitVersion execution step in `.github/workflows/dotnet.yml` test job.
- Comment out custom Git version generation target in `Versioning/Versioning.csproj` for future reference.
2025-07-29 17:59:42 -07:00
MSWS
2ee5b898f9 Fix versioning project name 2025-07-29 17:54:38 -07:00
MSWS
eee7cca182 Follow documentation for gittools 2025-07-29 17:51:39 -07:00
MSWS
7abca18738 Try disabling global flag 2025-07-29 17:46:46 -07:00
MSWS
1f0fc0cc34 ci: Install gitversion in CI 2025-07-29 17:44:42 -07:00
MSWS
528398acd6 Add DirectoryBuildProps to triggers 2025-07-29 17:42:38 -07:00
MSWS
2eeb1a2e93 build: Refactor GitVersion target and clean up build properties
- Refactor `Directory.Build.props`:
  - Add blank line between `<ItemGroup>` elements for clarity.
  - Remove redundant condition from `GitVersion.MsBuild` package reference.
  - Update `GenerateGitVersionInformation` target to execute `BeforeCompile` instead of `BeforeBuild`.
  - Replace `<PropertyGroup>` elements with explicit `<Exec>` commands in the `GenerateGitVersionInformation` target.
  - Modify `<Exec>` command syntax for consistency with other entries.
2025-07-29 17:40:51 -07:00
MSWS
f7e597ec1a Attempt to solve linux-specific issues 2025-07-29 17:37:28 -07:00
MSWS
999ba67d2b Additional unit testing and slight signature update 2025-07-29 16:50:34 -07:00
MSWS
c67bd3b919 feat: Add countdown parameter to game start method
- Update `Start` method across game logic to include a configurable countdown parameter
- Adjust `RoundBasedGameTest` to reflect new countdown logic and validate state transitions during delayed starts
- Modify `PlayerJoinGameStartListener` to pass a 5-second countdown when starting the game
- Update `IGame` interface to support countdown parameter in `Start` method and revise documentation accordingly
2025-07-29 16:31:11 -07:00
MSWS
a02583a800 Add Nix-OS specific files 2025-07-29 16:28:05 -07:00
MSWS
6ada09a37b Fix OS-specific issues 2025-07-29 16:14:10 -07:00
MSWS
c56b9f6e03 Tidy up repo 2025-07-29 15:52:53 -07:00
MSWS
33b8d1678f Format & Optimize 2025-07-28 23:11:38 -07:00
MSWS
905734ac3d test: Add tests and state handling for game start and rounds
- Rename `State.cs` in `TTT.Game` without modifying its content.
- Register `IGameManager` with `GameManager` implementation in `TTT.Test/Startup.cs`.
- Add new tests for joining games in `JoinStartTest.cs` to handle state transitions and messaging.
- Update logic in `RoundBasedGame.cs` to notify players of countdown interruptions and handle insufficient players during round start.
- Add `State` property to `IGame` interface and fix formatting in `TTT.Api/IGame.cs`.
- Simplify `DetectiveRole` constructor logic and clean up formatting in `TTT.Game/Roles/DetectiveRole.cs`.
2025-07-28 23:10:41 -07:00
MSWS
2e0a4e7ca4 Improve role balancing 2025-07-28 22:45:14 -07:00
MSWS
42ab80a350 Always generate code coverage summary 2025-07-28 21:41:34 -07:00
MSWS
4b78f49f08 ci: Simplify code coverage conditions in workflows
- Simplify code coverage conditional checks in dotnet workflow
- Remove conditional execution of export code coverage step based on .NET version
2025-07-28 21:34:38 -07:00
MSWS
7afe4c1445 ci: Update coverage file path in dotnet.yml workflow
Update coverage file path in GitHub Actions workflow

- Update the file path in `.github/workflows/dotnet.yml` to use a specific coverage file instead of a generic pattern.
2025-07-28 21:32:24 -07:00
MSWS
555951f898 ci: Update test coverage file path in dotnet workflow
Update test coverage file path in dotnet.yml workflow
2025-07-28 21:28:57 -07:00
MSWS
8464430503 ci: Add restore and build steps to test job in dotnet CI
Add steps for restoring dependencies and building in test job
2025-07-28 21:25:49 -07:00
MSWS
e92093439c ci: Simplify dotnet.yml test job and fix command syntax
- Update `.github/workflows/dotnet.yml` to streamline the test job by removing the dependency restoration step and unused commented-out build step, and adding quotes around the test command for consistency.
2025-07-28 21:23:40 -07:00
MSWS
f697c1bf43 ci: Update dotnet workflow to refine test job execution
- Update .NET GitHub Actions workflow
  - Comment out the build step in the test job
  - Adjust `dotnet run` command to include explicit `--project` flag
2025-07-28 21:17:20 -07:00
MSWS
7ca9acf195 ci: Align dotnet test workflow with build phase steps
- Update test job in dotnet.yml workflow to align processes with build phase
- Remove explicit project path from dotnet restore command in test job
2025-07-28 21:15:24 -07:00
MSWS
e3a46e4088 Fix path again 2025-07-28 21:11:49 -07:00
MSWS
7a993e81bc ci: Fix project paths in dotnet workflow commands
- Fix project path in restore dependencies command in dotnet.yml
- Update project path in dotnet run command in dotnet.yml
2025-07-28 21:09:54 -07:00
MSWS
9455e204c2 ci: Refactor and enhance project structure and tooling.
```
- Update `TTT.Api.csproj` to target .NET 8.0, add GitVersion.MsBuild reference, and retain existing package references.
- Modify `.github/workflows/dotnet.yml` to split test and build jobs, report code coverage, and introduce conditional tasks.
- Add code coverage badge to `README.md` and improve formatting.
- Remove debug-related properties and add GitVersion.MsBuild reference in `TTT.Game.csproj` and `TTT.CS2.csproj`.
- Clean up unused imports and update namespaces in `IPlayerConverter.cs` and other listener files to align with `TTT.Api.Player`.
```
2025-07-28 21:07:45 -07:00
MSWS
42ec1468a1 Re-enable debug symbols for code coverage 2025-07-28 20:35:34 -07:00
MSWS
08c2a67e4a build: Remove GenerateGitVersion tool and update TTT.Game debug settings
- Remove `GenerateGitVersion` project and related C# program
- Update `TTT.Game.csproj` to disable debug symbols and set debug type to none
2025-07-28 20:03:31 -07:00
MSWS
da569181a3 build: Refactor build configs and remove deprecated projects
```
- Remove "tools" and "GenerateGitVersion" projects from TTT.sln and their associated configuration and mappings.
- Update TTT.Plugin.csproj with improved publish configuration, including new properties, versioned ZIP output, and refined file handling.
- Disable debug symbols and set debug type to none in TTT.CS2.csproj.
```
2025-07-28 20:02:23 -07:00
MSWS
972f647a7a ci: Update workflow triggers for branches and paths
Update trigger configuration in dotnet workflow
2025-07-28 19:44:54 -07:00
MSWS
39b6190902 Disable caching in nightly 2025-07-28 19:44:05 -07:00
MSWS
267059b51b ci: Update GitHub Actions checkout configurations
- Fix formatting in `nightly.yml`
- Update `dotnet.yml` with enhanced `actions/checkout` configuration, including `fetch-depth` set to 0, enabled `fetch-tags`, and `show-progress`.
2025-07-28 19:42:02 -07:00
MSWS
61c059934b Start reworking gitversioning 2025-07-28 19:39:47 -07:00
MSWS
0aecb56de0 Update dotnet path 2025-07-28 19:23:30 -07:00
MSWS
effa2a277c Add workflows 2025-07-28 19:21:54 -07:00
MSWS
5df2a6e5f9 feat: Introduce reactive support and enhance DI across modules
```
Add new features, interfaces, and improve dependency injection across multiple components

- Update `IGameManager` interface to include the `ActiveGame` property and `CreateGame` method.
- Add `DelayAsync` method to the `IDelayer` interface for asynchronous delays utilizing `TimeSpan`.
- Implement dependency injection for `IOnlineMessenger`, `IRoleAssigner`, and `TestScheduler` in `TTT.Test/Startup.cs`.
- Enhance `FakeMessenger` to implement `IOnlineMessenger` and update messaging logic with stricter type validation and new methods.
- Modify `removePlayer` logic in `FakePlayerFinder` to use `Id` for player matching, with improved filtering via `RemoveWhere`.

- Register `IScheduler` in `TTTServiceCollection` and restructure module loading logic in `TTT.Plugin/TTT.cs`.
- Update `IGame` interface to make `Start` method return an `IObservable<long>` for reactive support.
- Implement new tests in `RoundBasedGameTest` to cover game state transitions based on players and delays.
```
2025-07-28 19:12:11 -07:00
MSWS
80201c94d5 Start work on concrete loading 2025-07-28 18:06:41 -07:00
MSWS
caa985023d Figure out time-based unit tests 2025-07-28 17:49:00 -07:00
MSWS
59ff2bd608 Format and add Windows Support 2025-07-28 15:18:52 -07:00
MSWS
e062d77955 feat: Introduce IRoleAssigner for role assignment refactor 2025-07-28 14:31:03 -07:00
MSWS
e4980eca4c Add more player methods 2025-07-28 14:12:22 -07:00
MSWS
c8b5941837 Reformat & Cleanup 2025-07-28 13:26:40 -07:00
MSWS
404fef40b0 More work on events 2025-07-28 13:26:14 -07:00
MSWS
c47851f4c5 Start work on messaging 2025-07-28 09:31:51 -07:00
MSWS
08adb86f65 Rename Test/Core -> Test/Game to match previous reorganization 2025-07-28 08:33:37 -07:00
MSWS
336335a854 Finish reorganizing 2025-07-28 08:29:20 -07:00
MSWS
a52885f586 Reorganize 2025-07-28 08:21:25 -07:00
MSWS
c935acb0a8 Figure out versioning again 2025-07-28 06:31:17 -07:00
MSWS
75af41c922 Move TTT.Core into repo 2025-07-28 05:49:17 -07:00
MSWS
4c76f089d3 Clean up repo, add event stuff 2025-07-28 05:44:29 -07:00
407 changed files with 18647 additions and 827 deletions

3
.envrc Normal file
View File

@@ -0,0 +1,3 @@
use nix
PATH_add ~/.dotnet/tools

14
.github/ISSUE_TEMPLATE/bug-report.md vendored Normal file
View File

@@ -0,0 +1,14 @@
---
name: Bug Report
about: Report an unintended behavior
title: ''
labels: 'Type: Bug'
assignees: ''
---
**Summary**
**Reproduction**
**Expected Behavior**

76
.github/changelogConfig.json vendored Normal file
View File

@@ -0,0 +1,76 @@
{
"template": "#{{CHANGELOG}}\n\n_#{{CONTRIBUTORS}} contributed across #{{COMMITS}} commits; see #{{RELEASE_DIFF}}_\n",
"pr_template": "- ##{{NUMBER}}: #{{TITLE}} (by @#{{AUTHOR}}) — ##{{URL}}",
"commit_template": "- #{{TITLE}}",
"empty_template": "- No changes",
"sort": { "order": "DESC", "on_property": "mergedAt" },
"ignore_labels": ["skip-changelog"],
"base_branches": ["main", "dev"],
"categories": [
{
"title": "## Breaking Changes",
"empty_content": "",
"rules": [
{ "pattern": "BREAKING CHANGE", "on_property": "body" },
{ "pattern": "!", "on_property": "title" }
],
"mode": "HYBRID"
},
{
"title": "## Features",
"labels": ["feature", "feat"]
},
{
"title": "## Fixes",
"labels": ["fix", "bug"]
},
{
"title": "## Security",
"labels": ["security", "vulnerability"]
},
{
"title": "## Performance",
"labels": ["perf"]
},
{
"title": "## Refactors",
"labels": ["refactor"]
},
{
"title": "## Docs",
"labels": ["docs", "documentation"]
},
{
"title": "## CI / CD",
"labels": ["ci", "cd", "build", "workflow", "test"]
},
{
"title": "## Dependencies",
"labels": ["dependencies", "dependabot"]
},
{
"title": "### Other",
"labels": []
}
],
"label_extractor": [
{
"pattern": "^(build|chore|ci|cd|workflow|docs|feat|feature|fix|bug|perf|refactor|revert|style|test){1}(\\([\\w\\-\\.]+\\))?(!)?: [\\s\\S]+$",
"on_property": "title",
"target": "$1"
}
],
"duplicate_filter": {
"pattern": "\\(#\\d+\\)$",
"on_property": "title",
"method": "match"
},
"reference": {
"pattern": "\\(#(\\d+)\\)",
"on_property": "body",
"method": "match",
"target": "$1"
},
"trim_values": true,
"max_back_track_time_days": 365
}

17
.github/dependabot.yml vendored Normal file
View File

@@ -0,0 +1,17 @@
# To get started with Dependabot version updates, you'll need to specify which
# package ecosystems to update and where the package manifests are located.
# Please see the documentation for all configuration options:
# https://docs.github.com/code-security/dependabot/dependabot-version-updates/configuration-options-for-the-dependabot.yml-file
version: 2
updates:
- package-ecosystem: "dotnet-sdk" # See documentation for possible values
directory: "/" # Location of package manifests
schedule:
interval: "weekly"
target-branch: "dev"
- package-ecosystem: "github-actions"
directory: "/" # Location of package manifests
schedule:
interval: "weekly"
target-branch: "dev"

104
.github/workflows/dotnet.yml vendored Normal file
View File

@@ -0,0 +1,104 @@
name: .NET Build and Test
on:
push:
branches:
- dev
pull_request:
concurrency:
group: ${{ github.head_ref || github.ref_name }}
cancel-in-progress: ${{ !( github.ref_name == 'main' || (github.event_name == 'pull_request' && github.event.pull_request.base.ref == 'main') ) }}
jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v5
with:
fetch-depth: 0
fetch-tags: true
show-progress: true
- name: Setup .NET
uses: actions/setup-dotnet@v5
with:
dotnet-version: '8.0.x'
- name: Restore dependencies
run: dotnet restore
- name: Build
run: dotnet build --no-restore
- name: Copy Locales
run: |
mkdir -p build_output/lang/
cp lang/*.json build_output/lang/
- name: Publish Test Project
run: dotnet publish TTT/Test/Test.csproj --no-restore --no-build -o build_output -c Debug
- uses: actions/upload-artifact@v4
with:
name: build_output
path: build_output
retention-days: 1
compression-level: '0'
test:
runs-on: ubuntu-latest
needs: build
permissions:
contents: read
pull-requests: write
steps:
- uses: actions/checkout@v5
- name: Setup .NET
uses: actions/setup-dotnet@v5
with:
dotnet-version: '8.0.x'
- name: Download Build Output
uses: actions/download-artifact@v5
with:
name: build_output
path: build_output
- name: Run tests
run: "dotnet ./build_output/Test.dll --coverage --coverage-output $GITHUB_WORKSPACE/coverage.xml --coverage-output-format cobertura"
- name: Code Coverage Summary Report
uses: irongut/CodeCoverageSummary@v1.3.0
with:
filename: 'coverage.xml'
badge: true
format: 'markdown'
output: 'both'
- name: Add Coverage PR Comment
uses: marocchino/sticky-pull-request-comment@v2
if: github.event_name == 'pull_request'
with:
recreate: true
path: code-coverage-results.md
- name: Export Code Coverage
run: echo "CODE_COVERAGE=$(tail -n 1 code-coverage-results.md | grep -oP '(?<=\*\*Summary\*\* \|\s\*\*)[0-9]+(?=%)')" >> $GITHUB_ENV
- name: Create Test Coverage Badge
uses: Schneegans/dynamic-badges-action@v1.7.0
id: create_coverage_badge
if: github.ref_name == 'main'
with:
auth: ${{ secrets.GIST_AUTH_TOKEN }}
gistID: 6289e1f34da3b70fbba5f84f5ffb25a1
filename: code-coverage.json
label: 'Code Coverage'
message: ${{ env.CODE_COVERAGE }}%
valColorRange: ${{ env.CODE_COVERAGE }}
maxColorRange: 100
minColorRange: 33
style: 'for-the-badge'
- name: Write to Job Summary
run: cat code-coverage-results.md >> $GITHUB_STEP_SUMMARY

88
.github/workflows/nightly.yml vendored Normal file
View File

@@ -0,0 +1,88 @@
name: Nightly
on:
push:
branches:
- dev
- main
paths:
- 'TTT/**'
- '.github/workflows/nightly.yml'
- '.github/workflows/release.yml'
schedule:
- cron: '15 0 * * 3' # Every Wednesday at 00:15 UTC
concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true
jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
with:
fetch-depth: 0
fetch-tags: true
show-progress: true
- name: Setup .NET SDK
uses: actions/setup-dotnet@v4
with:
dotnet-version: 8.0.x
- name: Install GitVersion
uses: GitTools/actions/gitversion/setup@v4.0.1
with:
versionSpec: '6.3.x'
- name: Run GitVersion
id: gitversion
uses: GitTools/actions/gitversion/execute@v4.0.1
- name: Output Version to Summary
run: "echo \"## GitVersion: ${{ steps.gitversion.outputs.fullSemVer }}\" >> $GITHUB_STEP_SUMMARY"
- name: Build Locale
run: |
mkdir -p build/TTT/lang
dotnet restore Locale/Locale.csproj
dotnet build Locale/Locale.csproj --no-restore -c Release
cp lang/*.json build/TTT/lang
- name: Copy Gamedata
run: |
mkdir -p build/TTT/gamedata
cp -r TTT/CS2/gamedata/* build/TTT/gamedata
- name: Publish Plugin
run: |
dotnet restore TTT/Plugin/Plugin.csproj
if [ "${GITHUB_REF##*/}" = "dev" ]; then
dotnet publish TTT/Plugin/Plugin.csproj --no-restore -c Debug -o build/TTT
elif [ "${GITHUB_REF##*/}" = "main" ]; then
dotnet publish TTT/Plugin/Plugin.csproj --no-restore -c Release -o build/TTT
else
echo "Branch not recognized, skipping publish."
exit 0
fi
- name: Upload Artifact
uses: actions/upload-artifact@v4
with:
name: TTT
path: build/TTT
if-no-files-found: error
post_webhook:
needs: build
runs-on: ubuntu-latest
if: github.ref == 'refs/heads/dev'
steps:
- name: POST Webhook
run: |
curl -X POST \
--fail \
-F token=${{ secrets.GITLAB_SECRET_TOKEN }} \
-F ref=dev \
https://gitlab.edgegamers.io/api/v4/projects/2640/trigger/pipeline

222
.github/workflows/release.yml vendored Normal file
View File

@@ -0,0 +1,222 @@
name: Auto Release on SemVer Change
on:
push:
branches:
- main
- dev
permissions:
contents: write
jobs:
auto-release:
runs-on: ubuntu-latest
env:
# Tweak these if you want a different model or style
OPENAI_MODEL: gpt-4o-mini
OPENAI_TEMPERATURE: "0.2"
# Safety: cap how many characters we feed to the model
MAX_CHANGELOG_CHARS: "50000"
steps:
- uses: actions/checkout@v5
with:
fetch-depth: 0
fetch-tags: true
# 1. Calculate version using GitVersion
- name: Install GitVersion
uses: gittools/actions/gitversion/setup@v4
with:
versionSpec: '6.3.x'
- name: Run GitVersion
id: gitversion
uses: gittools/actions/gitversion/execute@v4
- name: Build Locale
run: |
mkdir -p build/TTT/lang
dotnet restore Locale/Locale.csproj
dotnet build Locale/Locale.csproj --no-restore -c Release
cp lang/*.json build/TTT/lang
- name: Copy Gamedata
run: |
mkdir -p build/TTT/gamedata
cp -r TTT/CS2/gamedata/* build/TTT/gamedata
- name: Publish Plugin
run: |
dotnet restore TTT/Plugin/Plugin.csproj
dotnet publish TTT/Plugin/Plugin.csproj --no-restore -c Release -o build/TTT
- name: Zip Artifacts
run: |
cd build/TTT
zip -r TTT-${{ steps.gitversion.outputs.fullSemVer }}.zip *
# 2. Get latest tag
- name: Get latest tag
id: latest_tag
run: |
if git describe --tags --abbrev=0 >/dev/null 2>&1; then
echo "tag=$(git describe --tags --abbrev=0)" >> $GITHUB_OUTPUT
else
echo "tag=0.0.0" >> $GITHUB_OUTPUT
fi
# 3. Tag if new version
- name: Create and push new tag
if: steps.gitversion.outputs.fullSemVer != steps.latest_tag.outputs.tag
run: |
git config user.name "github-actions[bot]"
git config user.email "41898282+github-actions[bot]@users.noreply.github.com"
git tag ${{ steps.gitversion.outputs.fullSemVer }}
git push origin ${{ steps.gitversion.outputs.fullSemVer }}
# 4. Determine previous relevant tag (lineage-aware)
- name: Determine previous relevant tag
id: prev_tag
run: |
set -euo pipefail
branch="${GITHUB_REF_NAME}"
# Use HEAD^ to skip the tag we just created. If no parent, fall back to HEAD.
if git rev-parse --verify -q HEAD^ >/dev/null; then
base_rev="HEAD^"
else
base_rev="HEAD"
fi
# Match stable tags on main and prerelease tags on non-main
if [[ "$branch" == "main" ]]; then
pattern='[0-9]*.[0-9]*.[0-9]*'
else
pattern='[0-9]*.[0-9]*.[0-9]*-*'
fi
# Nearest tag reachable on this lineage, not just "second most recent by date"
prev=$(git describe --tags --abbrev=0 --match "$pattern" --tags "$base_rev" 2>/dev/null || true)
echo "tag=${prev:-0.0.0}" >> "$GITHUB_OUTPUT"
# 5. Generate changelog using local git (no compare API)
- name: Generate changelog
run: |
set -euo pipefail
prev="${{ steps.prev_tag.outputs.tag }}"
curr="${{ steps.gitversion.outputs.fullSemVer }}"
# Choose what you want in the raw feed: %s = subject only, %B = full message
GIT_LOG_FORMAT='%B'
if [[ "$prev" == "0.0.0" ]]; then
# First release: whole history to this tag, first-parent to reflect mains narrative
git log --no-merges --format="${GIT_LOG_FORMAT}" --reverse "$curr" > CHANGELOG.md
else
# Strict range between the previous reachable tag and the new tag on this lineage
git log --no-merges --format="${GIT_LOG_FORMAT}" --reverse "$prev..$curr" > CHANGELOG.md
fi
# Fallback in case nothing was captured
if [[ ! -s CHANGELOG.md ]]; then
echo "No commits found between $prev and $curr on first-parent. Using full messages without first-parent filter." >&2
if [[ "$prev" == "0.0.0" ]]; then
git log --no-merges --format="${GIT_LOG_FORMAT}" --reverse "$curr" > CHANGELOG.md
else
git log --no-merges --format="${GIT_LOG_FORMAT}" --reverse "$prev..$curr" > CHANGELOG.md
fi
fi
cat CHANGELOG.md
# 5b. Rewrite changelog with OpenAI
- name: Rewrite changelog with OpenAI
id: ai_changelog
if: success()
env:
OPENAI_API_KEY: ${{ secrets.OPENAI_API_KEY }}
OPENAI_MODEL: ${{ env.OPENAI_MODEL }}
OPENAI_TEMPERATURE: ${{ env.OPENAI_TEMPERATURE }}
MAX_CHANGELOG_CHARS: ${{ env.MAX_CHANGELOG_CHARS }}
run: |
set -euo pipefail
# Ensure we have a changelog to work with
if [[ ! -s CHANGELOG.md ]]; then
echo "CHANGELOG.md is empty. Skipping AI rewrite."
echo "skipped=true" >> $GITHUB_OUTPUT
exit 0
fi
# Trim the input to a safe size for token limits
head -c "${MAX_CHANGELOG_CHARS}" CHANGELOG.md > CHANGELOG_RAW.md
# Build the JSON body. We feed system guidance and the raw changelog
# See OpenAI Responses API docs for the schema and output_text helper. :contentReference[oaicite:0]{index=0}
jq -Rs --arg sys "You are an expert release-notes writer. Given a list of changes in various formats (e.g: commits, merges, etc.), write Release notes, grouping by features, features, and other pertinent groups where appropriate. Do not include a group if it is not necessary / populated. Remove internal ticket IDs and commit hashes unless essential. Merge duplicates. Use imperative, past tense voice voice. Output valid Markdown only." \
--arg temp "${OPENAI_TEMPERATURE}" \
--arg model "${OPENAI_MODEL}" \
'{model:$model, temperature: ($temp|tonumber), input:[{role:"system", content:$sys},{role:"user", content:.}]}' CHANGELOG_RAW.md > request.json
# Call the API
# Basic retry on transient failures
for i in 1 2 3; do
HTTP_CODE=$(curl -sS -w "%{http_code}" -o ai_response.json \
https://api.openai.com/v1/responses \
-H "Content-Type: application/json" \
-H "Authorization: Bearer $OPENAI_API_KEY" \
--data-binary @request.json) && break || true
echo "Call attempt $i failed with HTTP $HTTP_CODE"
sleep $((i*i))
done
if [[ "${HTTP_CODE:-000}" -lt 200 || "${HTTP_CODE:-000}" -ge 300 ]]; then
echo "OpenAI API call failed with HTTP $HTTP_CODE. Keeping raw changelog."
echo "skipped=true" >> $GITHUB_OUTPUT
exit 0
fi
# Prefer output_text if present. Fallback to first text item. :contentReference[oaicite:1]{index=1}
if jq -e '.output_text' ai_response.json >/dev/null; then
jq -r '.output_text' ai_response.json > CHANGELOG.md
else
jq -r '.output[0].content[] | select(.type=="output_text") | .text' ai_response.json | sed '/^[[:space:]]*$/d' > CHANGELOG.md
fi
# If the rewrite somehow produced an empty file, keep the raw one
if [[ ! -s CHANGELOG.md ]]; then
echo "AI returned empty content. Restoring raw changelog."
mv CHANGELOG_RAW.md CHANGELOG.md
echo "skipped=true" >> $GITHUB_OUTPUT
exit 0
fi
echo "skipped=false" >> $GITHUB_OUTPUT
echo "Rewritten changelog:"
cat CHANGELOG.md
# 6. Create release using the (possibly rewritten) changelog
- name: Create GitHub release
uses: softprops/action-gh-release@v2
with:
tag_name: ${{ steps.gitversion.outputs.fullSemVer }}
body_path: CHANGELOG.md
prerelease: ${{ github.ref_name != 'main' }}
files: build/TTT/*.zip
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
# 7. Cleanup old pre-releases
- name: Delete old pre-releases
if: github.ref_name != 'main'
run: |
gh release list --limit 100 --json name,isPrerelease \
--jq '.[] | select(.isPrerelease) | .name' | tail -n +11 | \
xargs -r -I {} gh release delete "{}" -y
env:
GH_TOKEN: ${{ github.token }}

61
.gitignore vendored
View File

@@ -1 +1,62 @@
.idea
# Gradle and Maven with auto-import
# When using Gradle or Maven with auto-import, you should exclude module files,
# since they will be recreated, and may cause churn. Uncomment if using
# auto-import.
# .idea/artifacts
# .idea/compiler.xml
# .idea/jarRepositories.xml
# .idea/modules.xml
# .idea/*.iml
# .idea/modules
# *.iml
# *.ipr
# CMake
cmake-build-*/
# Mongo Explorer plugin
.idea/**/mongoSettings.xml
# File-based project format
*.iws
# IntelliJ
out/
# mpeltonen/sbt-idea plugin
.idea_modules/
# JIRA plugin
atlassian-ide-plugin.xml
# Cursive Clojure plugin
.idea/replstate.xml
# SonarLint plugin
.idea/sonarlint/
# Crashlytics plugin (for Android Studio and IntelliJ)
com_crashlytics_export_strings.xml
crashlytics.properties
crashlytics-build.properties
fabric.properties
# Editor-based Rest Client
.idea/httpRequests
# Android studio 3.1+ serialized cache file
.idea/caches/build_file_checksums.ser
# End of https://www.toptal.com/developers/gitignore/api/rider
bin
obj
packages
*.user
build
GitVersionInformation.g.cs
gitversion.json
build_output
**/lang/*.json

30
CONTRIBUTING.md Normal file
View File

@@ -0,0 +1,30 @@
# Contributing to this Project
Thank you for considering contributing!
By submitting code, documentation, or other contributions ("Contributions") to this project, you agree that your
Contributions are licensed under the same terms as the projects license (the Profit Disclosure License v1.0).
This means your Contributions will be freely usable, modifiable, and distributable under that license.
Please ensure your Contributions are your original work or that you have the necessary rights to submit them.
Contributions that do not comply with the projects license or infringe third-party rights may be rejected.
---
**Code Formatting Requirement**
Before submitting, please format your code according to the settings provided in the `TTT.sln.DotSettings` file. This
helps maintain code consistency and quality.
---
For substantial contributions, maintainers may request you to sign a Contributor License Agreement (CLA) to clarify
rights and permissions.
---
If you have questions, please contact the repository owner.
Thank you for helping improve this project!

5
Directory.Build.props Normal file
View File

@@ -0,0 +1,5 @@
<Project>
<ItemGroup>
<PackageReference Include="JetBrains.Annotations" Version="2025.2.0"/>
</ItemGroup>
</Project>

View File

@@ -1,21 +0,0 @@
FROM mcr.microsoft.com/dotnet/runtime:8.0 AS base
USER $APP_UID
WORKDIR /app
FROM mcr.microsoft.com/dotnet/sdk:8.0 AS build
ARG BUILD_CONFIGURATION=Release
WORKDIR /src
COPY ["TTT.csproj", "./"]
RUN dotnet restore "TTT.csproj"
COPY . .
WORKDIR "/src/"
RUN dotnet build "./TTT.csproj" -c $BUILD_CONFIGURATION -o /app/build
FROM build AS publish
ARG BUILD_CONFIGURATION=Release
RUN dotnet publish "./TTT.csproj" -c $BUILD_CONFIGURATION -o /app/publish /p:UseAppHost=false
FROM base AS final
WORKDIR /app
COPY --from=publish /app/publish .
ENTRYPOINT ["dotnet", "TTT.dll"]

View File

@@ -1,2 +0,0 @@
<wpf:ResourceDictionary xml:space="preserve" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:s="clr-namespace:System;assembly=mscorlib" xmlns:ss="urn:shemas-jetbrains-com:settings-storage-xaml" xmlns:wpf="http://schemas.microsoft.com/winfx/2006/xaml/presentation">
<s:String x:Key="/Default/CodeInspection/ExcludedFiles/FilesAndFoldersToSkip2/=7020124F_002D9FFC_002D4AC3_002D8F3D_002DAAB8E0240759_002Ff_003AIDisposable_002Ecs_002Fl_003A_002E_002E_003F_002E_002E_003F_002E_002E_003F_002E_002E_003F_002E_002E_003F_002Econfig_003FJetBrains_003FRider2025_002E1_003Fresharper_002Dhost_003FDecompilerCache_003Fdecompiler_003F15495df23a5f432ab31b9c5df7609208b2e200_003F86_003Fa1f5f67f_003FIDisposable_002Ecs/@EntryIndexedValue">ForceIncluded</s:String></wpf:ResourceDictionary>

View File

@@ -1,95 +0,0 @@
<wpf:ResourceDictionary xml:space="preserve" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:s="clr-namespace:System;assembly=mscorlib" xmlns:ss="urn:shemas-jetbrains-com:settings-storage-xaml" xmlns:wpf="http://schemas.microsoft.com/winfx/2006/xaml/presentation">
<s:String x:Key="/Default/CodeStyle/CodeCleanup/RecentlyUsedProfile/@EntryValue">Built-in: Full Cleanup</s:String>
<s:String x:Key="/Default/CodeStyle/CodeFormatting/CSharpCodeStyle/MODIFIERS_ORDER/@EntryValue">public private override virtual file new abstract internal protected sealed static readonly extern unsafe volatile async required</s:String>
<s:String x:Key="/Default/CodeStyle/CodeFormatting/CSharpCodeStyle/PARENTHESES_REDUNDANCY_STYLE/@EntryValue">Remove</s:String>
<s:String x:Key="/Default/CodeStyle/CodeFormatting/CSharpCodeStyle/ThisQualifier/INSTANCE_MEMBERS_QUALIFY_DECLARED_IN/@EntryValue">0</s:String>
<s:String x:Key="/Default/CodeStyle/CodeFormatting/CSharpFormat/ACCESSOR_DECLARATION_BRACES/@EntryValue">END_OF_LINE</s:String>
<s:String x:Key="/Default/CodeStyle/CodeFormatting/CSharpFormat/ACCESSOR_OWNER_DECLARATION_BRACES/@EntryValue">END_OF_LINE</s:String>
<s:Boolean x:Key="/Default/CodeStyle/CodeFormatting/CSharpFormat/ALIGN_MULTILINE_BINARY_EXPRESSIONS_CHAIN/@EntryValue">False</s:Boolean>
<s:Boolean x:Key="/Default/CodeStyle/CodeFormatting/CSharpFormat/ALIGN_MULTILINE_STATEMENT_CONDITIONS/@EntryValue">False</s:Boolean>
<s:Boolean x:Key="/Default/CodeStyle/CodeFormatting/CSharpFormat/ALLOW_COMMENT_AFTER_LBRACE/@EntryValue">True</s:Boolean>
<s:String x:Key="/Default/CodeStyle/CodeFormatting/CSharpFormat/ANONYMOUS_METHOD_DECLARATION_BRACES/@EntryValue">END_OF_LINE</s:String>
<s:String x:Key="/Default/CodeStyle/CodeFormatting/CSharpFormat/CASE_BLOCK_BRACES/@EntryValue">END_OF_LINE</s:String>
<s:String x:Key="/Default/CodeStyle/CodeFormatting/CSharpFormat/EMPTY_BLOCK_STYLE/@EntryValue">TOGETHER_SAME_LINE</s:String>
<s:Boolean x:Key="/Default/CodeStyle/CodeFormatting/CSharpFormat/INDENT_BRACES_INSIDE_STATEMENT_CONDITIONS/@EntryValue">False</s:Boolean>
<s:Boolean x:Key="/Default/CodeStyle/CodeFormatting/CSharpFormat/INDENT_NESTED_FIXED_STMT/@EntryValue">True</s:Boolean>
<s:Boolean x:Key="/Default/CodeStyle/CodeFormatting/CSharpFormat/INDENT_NESTED_FOR_STMT/@EntryValue">True</s:Boolean>
<s:Boolean x:Key="/Default/CodeStyle/CodeFormatting/CSharpFormat/INDENT_NESTED_FOREACH_STMT/@EntryValue">True</s:Boolean>
<s:Boolean x:Key="/Default/CodeStyle/CodeFormatting/CSharpFormat/INDENT_NESTED_LOCK_STMT/@EntryValue">True</s:Boolean>
<s:Boolean x:Key="/Default/CodeStyle/CodeFormatting/CSharpFormat/INDENT_NESTED_USINGS_STMT/@EntryValue">True</s:Boolean>
<s:Boolean x:Key="/Default/CodeStyle/CodeFormatting/CSharpFormat/INDENT_NESTED_WHILE_STMT/@EntryValue">True</s:Boolean>
<s:String x:Key="/Default/CodeStyle/CodeFormatting/CSharpFormat/INDENT_RAW_LITERAL_STRING/@EntryValue">INDENT</s:String>
<s:Int64 x:Key="/Default/CodeStyle/CodeFormatting/CSharpFormat/INDENT_SIZE/@EntryValue">2</s:Int64>
<s:String x:Key="/Default/CodeStyle/CodeFormatting/CSharpFormat/INITIALIZER_BRACES/@EntryValue">END_OF_LINE</s:String>
<s:Boolean x:Key="/Default/CodeStyle/CodeFormatting/CSharpFormat/INT_ALIGN_ASSIGNMENTS/@EntryValue">True</s:Boolean>
<s:Boolean x:Key="/Default/CodeStyle/CodeFormatting/CSharpFormat/INT_ALIGN_COMMENTS/@EntryValue">True</s:Boolean>
<s:Boolean x:Key="/Default/CodeStyle/CodeFormatting/CSharpFormat/INT_ALIGN_PROPERTY_PATTERNS/@EntryValue">True</s:Boolean>
<s:Boolean x:Key="/Default/CodeStyle/CodeFormatting/CSharpFormat/INT_ALIGN_SWITCH_EXPRESSIONS/@EntryValue">True</s:Boolean>
<s:Boolean x:Key="/Default/CodeStyle/CodeFormatting/CSharpFormat/INT_ALIGN_SWITCH_SECTIONS/@EntryValue">True</s:Boolean>
<s:Boolean x:Key="/Default/CodeStyle/CodeFormatting/CSharpFormat/INT_ALIGN_VARIABLES/@EntryValue">True</s:Boolean>
<s:String x:Key="/Default/CodeStyle/CodeFormatting/CSharpFormat/INVOCABLE_DECLARATION_BRACES/@EntryValue">END_OF_LINE</s:String>
<s:Boolean x:Key="/Default/CodeStyle/CodeFormatting/CSharpFormat/KEEP_EXISTING_DECLARATION_PARENS_ARRANGEMENT/@EntryValue">False</s:Boolean>
<s:Boolean x:Key="/Default/CodeStyle/CodeFormatting/CSharpFormat/KEEP_EXISTING_EMBEDDED_ARRANGEMENT/@EntryValue">False</s:Boolean>
<s:Boolean x:Key="/Default/CodeStyle/CodeFormatting/CSharpFormat/KEEP_EXISTING_EXPR_MEMBER_ARRANGEMENT/@EntryValue">False</s:Boolean>
<s:Boolean x:Key="/Default/CodeStyle/CodeFormatting/CSharpFormat/KEEP_EXISTING_INITIALIZER_ARRANGEMENT/@EntryValue">False</s:Boolean>
<s:Boolean x:Key="/Default/CodeStyle/CodeFormatting/CSharpFormat/KEEP_EXISTING_INVOCATION_PARENS_ARRANGEMENT/@EntryValue">False</s:Boolean>
<s:Boolean x:Key="/Default/CodeStyle/CodeFormatting/CSharpFormat/KEEP_EXISTING_LIST_PATTERNS_ARRANGEMENT/@EntryValue">False</s:Boolean>
<s:Boolean x:Key="/Default/CodeStyle/CodeFormatting/CSharpFormat/KEEP_EXISTING_PRIMARY_CONSTRUCTOR_DECLARATION_PARENS_ARRANGEMENT/@EntryValue">False</s:Boolean>
<s:Boolean x:Key="/Default/CodeStyle/CodeFormatting/CSharpFormat/KEEP_EXISTING_PROPERTY_PATTERNS_ARRANGEMENT/@EntryValue">False</s:Boolean>
<s:Boolean x:Key="/Default/CodeStyle/CodeFormatting/CSharpFormat/KEEP_USER_LINEBREAKS/@EntryValue">False</s:Boolean>
<s:Int64 x:Key="/Default/CodeStyle/CodeFormatting/CSharpFormat/MAX_ARRAY_INITIALIZER_ELEMENTS_ON_LINE/@EntryValue">10</s:Int64>
<s:Int64 x:Key="/Default/CodeStyle/CodeFormatting/CSharpFormat/MAX_ENUM_MEMBERS_ON_LINE/@EntryValue">5</s:Int64>
<s:Int64 x:Key="/Default/CodeStyle/CodeFormatting/CSharpFormat/MAX_FORMAL_PARAMETERS_ON_LINE/@EntryValue">5</s:Int64>
<s:Int64 x:Key="/Default/CodeStyle/CodeFormatting/CSharpFormat/MAX_INVOCATION_ARGUMENTS_ON_LINE/@EntryValue">10</s:Int64>
<s:Int64 x:Key="/Default/CodeStyle/CodeFormatting/CSharpFormat/MAX_PRIMARY_CONSTRUCTOR_PARAMETERS_ON_LINE/@EntryValue">5</s:Int64>
<s:String x:Key="/Default/CodeStyle/CodeFormatting/CSharpFormat/NESTED_TERNARY_STYLE/@EntryValue">COMPACT</s:String>
<s:String x:Key="/Default/CodeStyle/CodeFormatting/CSharpFormat/OTHER_BRACES/@EntryValue">END_OF_LINE</s:String>
<s:Boolean x:Key="/Default/CodeStyle/CodeFormatting/CSharpFormat/OUTDENT_DOTS/@EntryValue">True</s:Boolean>
<s:Boolean x:Key="/Default/CodeStyle/CodeFormatting/CSharpFormat/OUTDENT_STATEMENT_LABELS/@EntryValue">True</s:Boolean>
<s:String x:Key="/Default/CodeStyle/CodeFormatting/CSharpFormat/PLACE_ACCESSOR_ATTRIBUTE_ON_SAME_LINE_EX/@EntryValue">NEVER</s:String>
<s:String x:Key="/Default/CodeStyle/CodeFormatting/CSharpFormat/PLACE_ACCESSORHOLDER_ATTRIBUTE_ON_SAME_LINE_EX/@EntryValue">NEVER</s:String>
<s:Boolean x:Key="/Default/CodeStyle/CodeFormatting/CSharpFormat/PLACE_CATCH_ON_NEW_LINE/@EntryValue">False</s:Boolean>
<s:Boolean x:Key="/Default/CodeStyle/CodeFormatting/CSharpFormat/PLACE_ELSE_ON_NEW_LINE/@EntryValue">False</s:Boolean>
<s:String x:Key="/Default/CodeStyle/CodeFormatting/CSharpFormat/PLACE_FIELD_ATTRIBUTE_ON_SAME_LINE_EX/@EntryValue">NEVER</s:String>
<s:Boolean x:Key="/Default/CodeStyle/CodeFormatting/CSharpFormat/PLACE_FINALLY_ON_NEW_LINE/@EntryValue">False</s:Boolean>
<s:Boolean x:Key="/Default/CodeStyle/CodeFormatting/CSharpFormat/PLACE_LINQ_INTO_ON_NEW_LINE/@EntryValue">False</s:Boolean>
<s:String x:Key="/Default/CodeStyle/CodeFormatting/CSharpFormat/PLACE_RECORD_FIELD_ATTRIBUTE_ON_SAME_LINE_EX/@EntryValue">NEVER</s:String>
<s:Boolean x:Key="/Default/CodeStyle/CodeFormatting/CSharpFormat/PLACE_SIMPLE_EMBEDDED_BLOCK_ON_SAME_LINE/@EntryValue">True</s:Boolean>
<s:Boolean x:Key="/Default/CodeStyle/CodeFormatting/CSharpFormat/PLACE_SIMPLE_METHOD_ON_SINGLE_LINE/@EntryValue">True</s:Boolean>
<s:Boolean x:Key="/Default/CodeStyle/CodeFormatting/CSharpFormat/PLACE_SIMPLE_SWITCH_EXPRESSION_ON_SINGLE_LINE/@EntryValue">True</s:Boolean>
<s:Boolean x:Key="/Default/CodeStyle/CodeFormatting/CSharpFormat/STICK_COMMENT/@EntryValue">False</s:Boolean>
<s:Int64 x:Key="/Default/CodeStyle/CodeFormatting/CSharpFormat/TAB_WIDTH/@EntryValue">2</s:Int64>
<s:String x:Key="/Default/CodeStyle/CodeFormatting/CSharpFormat/TYPE_DECLARATION_BRACES/@EntryValue">END_OF_LINE</s:String>
<s:Boolean x:Key="/Default/CodeStyle/CodeFormatting/CSharpFormat/WRAP_AFTER_PRIMARY_CONSTRUCTOR_DECLARATION_LPAR/@EntryValue">False</s:Boolean>
<s:Boolean x:Key="/Default/CodeStyle/CodeFormatting/CSharpFormat/WRAP_BEFORE_ARROW_WITH_EXPRESSIONS/@EntryValue">True</s:Boolean>
<s:Boolean x:Key="/Default/CodeStyle/CodeFormatting/CSharpFormat/WRAP_BEFORE_BINARY_OPSIGN/@EntryValue">True</s:Boolean>
<s:Boolean x:Key="/Default/CodeStyle/CodeFormatting/CSharpFormat/WRAP_BEFORE_TERNARY_OPSIGNS/@EntryValue">False</s:Boolean>
<s:String x:Key="/Default/CodeStyle/CodeFormatting/CSharpFormat/WRAP_CHAINED_METHOD_CALLS/@EntryValue">CHOP_IF_LONG</s:String>
<s:String x:Key="/Default/CodeStyle/CodeFormatting/CSharpFormat/WRAP_ENUM_DECLARATION/@EntryValue">CHOP_IF_LONG</s:String>
<s:String x:Key="/Default/CodeStyle/CodeFormatting/CSharpFormat/WRAP_FOR_STMT_HEADER_STYLE/@EntryValue">WRAP_IF_LONG</s:String>
<s:Int64 x:Key="/Default/CodeStyle/CodeFormatting/CSharpFormat/WRAP_LIMIT/@EntryValue">80</s:Int64>
<s:String x:Key="/Default/CodeStyle/CodeFormatting/CSharpFormat/WRAP_PRIMARY_CONSTRUCTOR_PARAMETERS_STYLE/@EntryValue">WRAP_IF_LONG</s:String>
<s:Boolean x:Key="/Default/CodeStyle/Naming/CSharpAutoNaming/IsNotificationDisabled/@EntryValue">True</s:Boolean>
<s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/Abbreviations/=API/@EntryIndexedValue">API</s:String>
<s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/Abbreviations/=IO/@EntryIndexedValue">IO</s:String>
<s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/Abbreviations/=LG/@EntryIndexedValue">LG</s:String>
<s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/Abbreviations/=LR/@EntryIndexedValue">LR</s:String>
<s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/Abbreviations/=ST/@EntryIndexedValue">ST</s:String>
<s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/UserRules/=08582792_002Dd334_002D4f6d_002Db467_002Dfc7b9fd4557b/@EntryIndexedValue">&lt;Policy&gt;&lt;Descriptor Staticness="Any" AccessRightKinds="Private, ProtectedInternal, Internal, PrivateProtected" Description="Non-Public Methods"&gt;&lt;ElementKinds&gt;&lt;Kind Name="METHOD" /&gt;&lt;/ElementKinds&gt;&lt;/Descriptor&gt;&lt;Policy Inspect="True" Prefix="" Suffix="" Style="aaBb" /&gt;&lt;/Policy&gt;</s:String>
<s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/UserRules/=15b5b1f1_002D457c_002D4ca6_002Db278_002D5615aedc07d3/@EntryIndexedValue">&lt;Policy&gt;&lt;Descriptor Staticness="Static" AccessRightKinds="Private" Description="Static readonly fields (private)"&gt;&lt;ElementKinds&gt;&lt;Kind Name="READONLY_FIELD" /&gt;&lt;/ElementKinds&gt;&lt;/Descriptor&gt;&lt;Policy Inspect="True" Prefix="" Suffix="" Style="AA_BB" /&gt;&lt;/Policy&gt;</s:String>
<s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/UserRules/=236f7aa5_002D7b06_002D43ca_002Dbf2a_002D9b31bfcff09a/@EntryIndexedValue">&lt;Policy&gt;&lt;Descriptor Staticness="Any" AccessRightKinds="Private" Description="Constant fields (private)"&gt;&lt;ElementKinds&gt;&lt;Kind Name="CONSTANT_FIELD" /&gt;&lt;/ElementKinds&gt;&lt;/Descriptor&gt;&lt;Policy Inspect="True" Prefix="" Suffix="" Style="AA_BB" /&gt;&lt;/Policy&gt;</s:String>
<s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/UserRules/=4a98fdf6_002D7d98_002D4f5a_002Dafeb_002Dea44ad98c70c/@EntryIndexedValue">&lt;Policy&gt;&lt;Descriptor Staticness="Instance" AccessRightKinds="Private" Description="Instance fields (private)"&gt;&lt;ElementKinds&gt;&lt;Kind Name="FIELD" /&gt;&lt;Kind Name="READONLY_FIELD" /&gt;&lt;/ElementKinds&gt;&lt;/Descriptor&gt;&lt;Policy Inspect="True" Prefix="" Suffix="" Style="aaBb" /&gt;&lt;/Policy&gt;</s:String>
<s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/UserRules/=669e5282_002Dfb4b_002D4e90_002D91e7_002D07d269d04b60/@EntryIndexedValue">&lt;Policy&gt;&lt;Descriptor Staticness="Any" AccessRightKinds="Protected, ProtectedInternal, Internal, Public, PrivateProtected" Description="Constant fields (not private)"&gt;&lt;ElementKinds&gt;&lt;Kind Name="CONSTANT_FIELD" /&gt;&lt;/ElementKinds&gt;&lt;/Descriptor&gt;&lt;Policy Inspect="True" Prefix="" Suffix="" Style="AA_BB" /&gt;&lt;/Policy&gt;</s:String>
<s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/UserRules/=8284009d_002De743_002D4d89_002D9402_002Da5bf9a89b657/@EntryIndexedValue">&lt;Policy&gt;&lt;Descriptor Staticness="Any" AccessRightKinds="Protected, Public, FileLocal" Description="Public Methods"&gt;&lt;ElementKinds&gt;&lt;Kind Name="METHOD" /&gt;&lt;/ElementKinds&gt;&lt;/Descriptor&gt;&lt;Policy Inspect="True" Prefix="" Suffix="" Style="AaBb" /&gt;&lt;/Policy&gt;</s:String>
<s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/UserRules/=8a85b61a_002D1024_002D4f87_002Db9ef_002D1fdae19930a1/@EntryIndexedValue">&lt;Policy&gt;&lt;Descriptor Staticness="Any" AccessRightKinds="Any" Description="Parameters"&gt;&lt;ElementKinds&gt;&lt;Kind Name="PARAMETER" /&gt;&lt;/ElementKinds&gt;&lt;/Descriptor&gt;&lt;Policy Inspect="True" Prefix="" Suffix="" Style="aaBb"&gt;&lt;ExtraRule Prefix="_" Suffix="" Style="aaBb" /&gt;&lt;/Policy&gt;&lt;/Policy&gt;</s:String>
<s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/UserRules/=8b8504e3_002Df0be_002D4c14_002D9103_002Dc732f2bddc15/@EntryIndexedValue">&lt;Policy&gt;&lt;Descriptor Staticness="Any" AccessRightKinds="Any" Description="Enum members"&gt;&lt;ElementKinds&gt;&lt;Kind Name="ENUM_MEMBER" /&gt;&lt;/ElementKinds&gt;&lt;/Descriptor&gt;&lt;Policy Inspect="True" Prefix="" Suffix="" Style="AA_BB" /&gt;&lt;/Policy&gt;</s:String>
<s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/UserRules/=c873eafb_002Dd57f_002D481d_002D8c93_002D77f6863c2f88/@EntryIndexedValue">&lt;Policy&gt;&lt;Descriptor Staticness="Static" AccessRightKinds="Protected, ProtectedInternal, Internal, Public, PrivateProtected" Description="Static readonly fields (not private)"&gt;&lt;ElementKinds&gt;&lt;Kind Name="READONLY_FIELD" /&gt;&lt;/ElementKinds&gt;&lt;/Descriptor&gt;&lt;Policy Inspect="True" Prefix="" Suffix="" Style="AA_BB" /&gt;&lt;/Policy&gt;</s:String>
<s:Boolean x:Key="/Default/Environment/SettingsMigration/IsMigratorApplied/=JetBrains_002EReSharper_002EPsi_002ECSharp_002ECodeStyle_002ECSharpKeepExistingMigration/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/Environment/SettingsMigration/IsMigratorApplied/=JetBrains_002EReSharper_002EPsi_002ECSharp_002ECodeStyle_002ECSharpPlaceEmbeddedOnSameLineMigration/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/Environment/SettingsMigration/IsMigratorApplied/=JetBrains_002EReSharper_002EPsi_002ECSharp_002ECodeStyle_002ECSharpUseContinuousIndentInsideBracesMigration/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/Environment/SettingsMigration/IsMigratorApplied/=JetBrains_002EReSharper_002EPsi_002ECSharp_002ECodeStyle_002ESettingsUpgrade_002EMigrateBlankLinesAroundFieldToBlankLinesAroundProperty/@EntryIndexedValue">True</s:Boolean>
</wpf:ResourceDictionary>

42
GitVersion.yml Normal file
View File

@@ -0,0 +1,42 @@
mode: ContinuousDeployment
tag-prefix: "" # allow bare numeric tags like 2.0.0
commit-message-incrementing: Enabled
assembly-versioning-scheme: MajorMinorPatch
# Never allow commit messages to trigger a major bump
major-version-bump-message: "(?!)"
# Opt-in bumps via tokens
minor-version-bump-message: \+semver:\s?minor
patch-version-bump-message: \+semver:\s?patch
branches:
main:
label: "" # clears the default prerelease label
increment: None # no automatic bump unless +semver token
prevent-increment:
of-merged-branch: true
when-branch-merged: true
when-current-commit-tagged: true
develop:
label: "dev"
increment: None
prevent-increment:
of-merged-branch: true
when-branch-merged: true
when-current-commit-tagged: true
feature:
label: "feat"
increment: None
release:
label: "rc"
increment: None
hotfix:
label: "hotfix"
increment: None
pull-request:
label: "pr"
increment: None
assembly-informational-format: "{FullSemVer}+Branch.{BranchName}.Sha.{ShortSha}"

View File

@@ -1,39 +0,0 @@
namespace GitVersion
{
internal static class GitVersionInformation
{
public const int Major = 0;
public const int Minor = 1;
public const int Patch = 0;
public const string PreReleaseTag = "";
public const string PreReleaseTagWithDash = "";
public const string PreReleaseLabel = "";
public const string PreReleaseLabelWithDash = "";
// PreReleaseNumber is null and omitted
public const int WeightedPreReleaseNumber = 60000;
public const int BuildMetaData = 0;
public const string BuildMetaDataPadded = "0000";
public const string FullBuildMetaData = "0.Branch.main.Sha.e0f450147592475d2373504f6eee595d4edb9f3a";
public const string MajorMinorPatch = "0.1.0";
public const string SemVer = "0.1.0";
public const string LegacySemVer = "0.1.0";
public const string LegacySemVerPadded = "0.1.0";
public const string AssemblySemVer = "0.1.0.0";
public const string AssemblySemFileVer = "0.1.0.0";
public const string FullSemVer = "0.1.0+0";
public const string InformationalVersion = "0.1.0+0.Branch.main.Sha.e0f450147592475d2373504f6eee595d4edb9f3a";
public const string BranchName = "main";
public const string EscapedBranchName = "main";
public const string Sha = "e0f450147592475d2373504f6eee595d4edb9f3a";
public const string ShortSha = "e0f4501";
public const string NuGetVersionV2 = "0.1.0";
public const string NuGetVersion = "0.1.0";
public const string NuGetPreReleaseTagV2 = "";
public const string NuGetPreReleaseTag = "";
public const string VersionSourceSha = "e0f450147592475d2373504f6eee595d4edb9f3a";
public const int CommitsSinceVersionSource = 0;
public const string CommitsSinceVersionSourcePadded = "0000";
public const int UncommittedChanges = 8;
public const string CommitDate = "2025-07-28";
}
}

83
LICENSE Normal file
View File

@@ -0,0 +1,83 @@
Profit Disclosure License v1.0
==================================
Copyright (c) 2025 Isaac Boaz
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to use,
copy, modify, and distribute the Software, subject to the following conditions:
1. Definitions
--------------
"Modified versions" means any work containing the Software altered or
adapted in any way.
"Derivative works" means works based upon the Software, including
translations, adaptations, or other modifications.
"Combined works" means any software that relies on, depends on, builds on,
or requires the Software to function in whole or in part.
2. Non-Commercial Use
---------------------
You may use, copy, modify, and distribute the Software freely for any
non-commercial purpose, provided that this license and the above copyright
notice are included in all copies or substantial portions of the Software.
3. Commercial and Monetized Network Use Obligations
---------------------------------------------------
If the Software, or any portion of it, is used in a project, product, service,
or network-accessible application (e.g., SaaS, PaaS, hosted application) that
generates revenue or is intended for commercial gain, whether direct or indirect,
you must:
a) Make the complete and corresponding source code of any modified versions,
derivative works, or combined works that include or depend on the Software
publicly and freely available under the terms of this same license; and
b) Provide a clear and prominent offer to all users and customers of the
commercial product, service, or network application to obtain the full source
code free of charge.
4. Definition of Commercial Use
-------------------------------
"Commercial use" includes, but is not limited to:
- Selling or licensing the Software or any derivative or combined work;
- Offering the Software as part of a paid product or service;
- Using the Software to provide services for a fee;
- Monetizing access via advertising, subscriptions, or affiliates;
- Internal use by for-profit entities in products that are not themselves
open-sourced.
5. Patent Grant
---------------
The copyright holder grants you a limited, non-exclusive,
royalty-free patent license to use, make, and distribute the Software as
permitted by this license. This grant does not include any patent rights not
necessarily infringed by the Software.
6. No Sublicensing
------------------
You may not sublicense the Software under terms more permissive than this
license.
7. Termination
--------------
Any violation of this license terminates your rights under it immediately.
Rights may be reinstated if you cure the violation within 30 days of notice.
8. Governing Law and Jurisdiction
---------------------------------
This license shall be governed by and construed in accordance with the laws of
the jurisdiction where the copyright holder resides, without regard to conflict
of law principles. Any dispute shall be resolved exclusively in the courts of
that jurisdiction.
9. No Warranty
--------------
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES, OR OTHER LIABILITY, WHETHER IN AN
ACTION OF CONTRACT, TORT, OR OTHERWISE, ARISING FROM, OUT OF, OR IN
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
SPDX-License-Identifier: Profit-Disclosure-1.0

18
LICENSES.MD Normal file
View File

@@ -0,0 +1,18 @@
| Package | Version | License Information Origin | License Expression | License Url | Copyright | Authors | Package Project Url |
| ----------------------------------------------------- | -------- | -------------------------- | ------------------ | --------------------------------------- | ----------------------------------------------- | ------------------------------------ | ------------------------------------------------------------------------------------------------ |
| CounterStrikeSharp.API | 1.0.332 | Expression | GPL-3.0-only | https://licenses.nuget.org/GPL-3.0-only | | Roflmuffin | http://docs.cssharp.dev/ |
| CounterStrikeSharp.API | 1.0.340 | Expression | GPL-3.0-only | https://licenses.nuget.org/GPL-3.0-only | | Roflmuffin | http://docs.cssharp.dev/ |
| Dapper | 2.1.66 | Expression | Apache-2.0 | https://licenses.nuget.org/Apache-2.0 | 2019 Stack Exchange, Inc. | Sam Saffron,Marc Gravell,Nick Craver | https://github.com/DapperLib/Dapper |
| JetBrains.Annotations | 2025.2.0 | Expression | MIT | https://licenses.nuget.org/MIT | Copyright (c) 2016-2025 JetBrains s.r.o. | JetBrains | https://www.jetbrains.com/help/resharper/Code_Analysis__Code_Annotations.html |
| Microsoft.Extensions.DependencyInjection.Abstractions | 9.0.7 | Expression | MIT | https://licenses.nuget.org/MIT | © Microsoft Corporation. All rights reserved. | Microsoft | https://dot.net/ |
| Microsoft.Extensions.Localization.Abstractions | 8.0.3 | Expression | MIT | https://licenses.nuget.org/MIT | © Microsoft Corporation. All rights reserved. | Microsoft | https://asp.net/ |
| Microsoft.NET.Test.Sdk | 17.14.1 | Expression | MIT | https://licenses.nuget.org/MIT | © Microsoft Corporation. All rights reserved. | Microsoft | https://github.com/microsoft/vstest |
| Microsoft.Reactive.Testing | 6.0.1 | Expression | MIT | https://licenses.nuget.org/MIT | Copyright (c) .NET Foundation and Contributors. | .NET Foundation and Contributors | https://github.com/dotnet/reactive |
| Microsoft.Testing.Extensions.CodeCoverage | 17.14.2 | Unknown | | https://aka.ms/deprecateLicenseUrl | © Microsoft Corporation. All rights reserved. | Microsoft | https://github.com/microsoft/codecoverage |
| MySqlConnector | 2.4.0 | Expression | MIT | https://licenses.nuget.org/MIT | Copyright 20162024 Bradley Grainger | Bradley Grainger | https://mysqlconnector.net/ |
| System.Reactive | 6.0.1 | Expression | MIT | https://licenses.nuget.org/MIT | Copyright (c) .NET Foundation and Contributors. | .NET Foundation and Contributors | https://github.com/dotnet/reactive |
| System.Text.Json | 8.0.5 | Expression | MIT | https://licenses.nuget.org/MIT | © Microsoft Corporation. All rights reserved. | Microsoft | https://dot.net/ |
| Xunit.DependencyInjection | 10.6.0 | Expression | MIT | https://licenses.nuget.org/MIT | Copyright © 2019 | Wei Peng | https://github.com/pengweiqhca/Xunit.DependencyInjection/tree/main/src/Xunit.DependencyInjection |
| xunit.runner.visualstudio | 3.1.3 | Expression | Apache-2.0 | https://licenses.nuget.org/Apache-2.0 | Copyright (C) .NET Foundation | jnewkirk,bradwilson | |
| xunit.v3 | 3.0.0 | Expression | Apache-2.0 | https://licenses.nuget.org/Apache-2.0 | Copyright (C) .NET Foundation | jnewkirk,bradwilson | |
| YamlDotNet | 16.3.0 | Expression | MIT | https://licenses.nuget.org/MIT | Copyright (c) Antoine Aubry and contributors | Antoine Aubry | https://github.com/aaubry/YamlDotNet/wiki |

6
Locale/IMsg.cs Normal file
View File

@@ -0,0 +1,6 @@
namespace TTT.Locale;
public interface IMsg {
string Key { get; }
object[] Args { get; }
}

7
Locale/IMsgLocalizer.cs Normal file
View File

@@ -0,0 +1,7 @@
using Microsoft.Extensions.Localization;
namespace TTT.Locale;
public interface IMsgLocalizer : IStringLocalizer {
string this[IMsg msg] { get; }
}

View File

@@ -0,0 +1,29 @@
using CounterStrikeSharp.API.Core.Translations;
using Microsoft.Extensions.Localization;
namespace TTT.Locale;
public class JsonLocalizerFactory : IStringLocalizerFactory {
private readonly string langPath;
public JsonLocalizerFactory() {
// Lang folder is in the root of the project
// keep moving up until we find it
var current = Directory.GetCurrentDirectory();
while (!File.Exists(Path.Combine(current, "lang", "en.json"))) {
current = Directory.GetParent(current)?.FullName;
if (current == null)
throw new DirectoryNotFoundException("Could not find lang folder");
}
langPath = Path.Combine(current, "lang");
}
public IStringLocalizer Create(Type resourceSource) {
return new JsonStringLocalizer(langPath);
}
public IStringLocalizer Create(string baseName, string location) {
return new JsonStringLocalizer(langPath);
}
}

38
Locale/Locale.csproj Normal file
View File

@@ -0,0 +1,38 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>net8.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
<RootNamespace>TTT.Locale</RootNamespace>
<OutputType>Exe</OutputType>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="CounterStrikeSharp.API" Version="1.0.332"/>
<PackageReference Include="Microsoft.Extensions.Localization.Abstractions" Version="8.0.3"/>
<PackageReference Include="System.Text.Json" Version="8.0.5"/>
<PackageReference Include="YamlDotNet" Version="16.3.0"/>
</ItemGroup>
<Target Name="PreprocessYaml" AfterTargets="Build;VSTest">
<PropertyGroup>
<LocaleDllPath>$(MSBuildProjectDirectory)\bin\$(Configuration)\net8.0\$(AssemblyName).dll</LocaleDllPath>
<MasterJsonPath>$(MSBuildProjectDirectory)\..\lang\en.json</MasterJsonPath>
</PropertyGroup>
<ItemGroup>
<LangFiles Include="..\**\lang\*.yml"/>
<!-- Exclude Test/lang/en.yml only in Release config -->
<LangFiles Remove="..\TTT\Test\lang\en.yml" Condition="'$(Configuration)' == 'Release'"/>
</ItemGroup>
<Message Importance="high" Text="Combining YAML files into $(MasterJsonPath)"/>
<Message Importance="high" Text="Included YAML files:"/>
<Message Importance="high" Text=" %(LangFiles.FullPath)" Condition="'%(LangFiles.FullPath)' != ''"/>
<Exec Command="dotnet &quot;$(LocaleDllPath)&quot; @(LangFiles->'&quot;%(FullPath)&quot;', ' ') --out &quot;$(MasterJsonPath)&quot;"/>
</Target>
</Project>

9
Locale/MsgFactory.cs Normal file
View File

@@ -0,0 +1,9 @@
namespace TTT.Locale;
public static class MsgFactory {
public static IMsg Create(string key, params object[] args) {
return new Msg(key, args);
}
private sealed record Msg(string Key, object[] Args) : IMsg;
}

97
Locale/Program.cs Normal file
View File

@@ -0,0 +1,97 @@
using System.Text.Json;
using YamlDotNet.Serialization;
using YamlDotNet.Serialization.NamingConventions;
namespace TTT.Locale;
public static class Program {
private static readonly JsonSerializerOptions opts =
new() { WriteIndented = true };
public static void Main(string[] args) {
if (args.Length < 1) {
printUsage();
Environment.Exit(1);
}
var (inputPaths, outputPath) = parseArguments(args);
validateInputFiles(inputPaths);
var merged = mergeYamlFiles(inputPaths);
writeJsonOutput(merged, outputPath);
}
private static void printUsage() {
Console.Error.WriteLine("Usage:");
Console.Error.WriteLine(" YamlToJson <input.yml>");
Console.Error.WriteLine(
" YamlToJson <input1.yml> <input2.yml> ... --out <output.json>");
}
private static (string[] inputPaths, string outputPath) parseArguments(
string[] args) {
string outputPath;
string[] inputPaths;
if (args.Length == 1) {
inputPaths = [args[0]];
outputPath = Path.ChangeExtension(args[0], ".json");
} else {
var outIndex = Array.IndexOf(args, "--out");
if (outIndex == -1 || outIndex == args.Length - 1 || outIndex < 1) {
Console.Error.WriteLine(
"Error: When specifying multiple input files, use: --out <output.json>");
Environment.Exit(1);
}
outputPath = args[outIndex + 1];
inputPaths = args.Take(outIndex).ToArray();
}
return (inputPaths, outputPath);
}
private static void validateInputFiles(string[] inputPaths) {
foreach (var input in inputPaths)
if (!File.Exists(input)) {
Console.Error.WriteLine($"Error: File not found - {input}");
Environment.Exit(2);
}
}
private static Dictionary<string, string>
mergeYamlFiles(string[] inputPaths) {
var deserializer = new DeserializerBuilder()
.WithNamingConvention(NullNamingConvention.Instance)
.Build();
var merged = new Dictionary<string, string>();
foreach (var input in inputPaths) {
var yaml = File.ReadAllText(input);
var parsed = deserializer.Deserialize<Dictionary<string, string>>(yaml);
foreach (var (k, v) in parsed) {
if (merged.TryGetValue(k, out var existing) && existing != v)
Console.Error.WriteLine(
$"Warning: Duplicate key '{k}' found in {input}, overwriting value.");
merged[k] = v; // Overwrite if duplicate
}
}
return merged;
}
private static void writeJsonOutput(Dictionary<string, string> merged,
string outputPath) {
var dir = Path.GetDirectoryName(outputPath);
if (!string.IsNullOrEmpty(dir) && !Directory.Exists(dir))
Directory.CreateDirectory(dir);
var json = JsonSerializer.Serialize(merged, opts);
File.WriteAllText(outputPath, json);
}
}

20
Locale/README.md Normal file
View File

@@ -0,0 +1,20 @@
# TTT - Localizer
Responsible for managing the translations of the different TTT modules.
In and of itself does not provide any translations, but rather provides a framework for other modules to provide their
own translations.
For convenience, Localizer runs as a CLI tool that converts YML files to JSON files, as YML is nicer to work with, but
JSON is the format used for [CounterStrikeSharp](https://github.com/roflmuffin/CounterStrikeSharp)'s localization
system.
## Usage
1. Build (`dotnet build`)
2. Navigate to where the Localizer.dll is
3. Run `dotnet Localizer.dll [input files...] -o [output file]`
- CS# sources all translations from the single `.json` file; separating the YML files allows for easier management per
module, the localizer will combine them into a single JSON file.
- If you are only providing one input file, you can omit the `-o` flag and it will output to `inputFileName.json` by
default.

168
Locale/StringLocalizer.cs Normal file
View File

@@ -0,0 +1,168 @@
using System.Reflection;
using System.Text.RegularExpressions;
using Microsoft.Extensions.Localization;
namespace TTT.Locale;
/// <summary>
/// A custom implementation of <see cref="IStringLocalizer" /> that adds support
/// for in-string placeholders like %key% and grammatical pluralization with %s%.
/// </summary>
public partial class StringLocalizer : IMsgLocalizer {
private readonly IStringLocalizer localizer;
public StringLocalizer(IStringLocalizerFactory factory) {
var type = typeof(StringLocalizer);
var assemblyName =
new AssemblyName(type.GetTypeInfo().Assembly.FullName ?? string.Empty);
localizer = factory.Create(string.Empty, assemblyName.FullName);
}
public string this[IMsg msg] => getString(msg.Key, msg.Args);
public LocalizedString this[string name] => getString(name);
public LocalizedString this[string name, params object[] arguments]
=> getString(name, arguments);
public IEnumerable<LocalizedString>
GetAllStrings(bool includeParentCultures) {
return localizer.GetAllStrings(includeParentCultures)
.Select(str => getString(str.Name));
}
[GeneratedRegex("%.*?%")]
private static partial Regex percentRegex();
[GeneratedRegex(@"\b(\w+)%s%")]
private static partial Regex pluralRegex();
[GeneratedRegex(@"%an%", RegexOptions.IgnoreCase)]
private static partial Regex anRegex();
private LocalizedString getString(string name, params object[] arguments) {
// Get the localized value
string value;
try { value = localizer[name].Value; } catch (NullReferenceException e) {
return new LocalizedString(name, name, true);
}
// Replace placeholders like %key% with their respective values
var matches = percentRegex().Matches(value);
foreach (Match match in matches) {
var key = match.Value;
var trimmedKey = key[1..^1]; // Trim % symbols
// NullReferenceException catch block if key does not exist
try {
// CS# forces a space before a chat color if the entirety
// of the strong is a color code. This is undesired
// in our case, so we trim the value when we have a prefix.
var replacement = localizer[trimmedKey].Value;
if (replacement == trimmedKey) continue;
value = value.Replace(key,
trimmedKey.Contains("PREFIX", StringComparison.OrdinalIgnoreCase) ?
replacement :
replacement.TrimStart());
} catch (NullReferenceException) {
// Key doesn't exist, move on
}
}
// Format with arguments if provided
if (arguments.Length > 0) value = string.Format(value, arguments);
// Handle pluralization
value = HandlePluralization(value);
value = HandleAn(value);
if (!string.IsNullOrWhiteSpace(value) && hasChatColor(value)) {
var first = value.First(c => !char.IsWhiteSpace(c));
if (char.IsAsciiLetterOrDigit(first)) value = value.TrimStart();
}
return new LocalizedString(name, value);
}
private static bool isChatColor(char c) {
return c is '\x01' or '\x02' or '\x03' or '\x04' or '\x05' or '\x06'
or '\x07' or '\x08' or '\x09' or '\x0A' or '\x0B' or '\x0C' or '\x0D'
or '\x0E' or '\x0F' or '\x10';
}
private static bool hasChatColor(string value) {
return value.Any(isChatColor);
}
public static string HandlePluralization(string value) {
var pluralMatches = pluralRegex().Matches(value);
foreach (Match match in pluralMatches) {
var word = match.Groups[1].Value.ToLower();
var index = match.Index;
var prefix = value[..index].Trim();
var lastWords = prefix.Split(' ')
.Select(w
=> w.Where(c => char.IsLetterOrDigit(c) || c == '-').ToArray());
var previousNumber = lastWords.LastOrDefault(w => int.TryParse(w, out _));
if (previousNumber != null)
value = value[..index] + value[index..]
.Replace("%s%", int.Parse(previousNumber) == 1 ? "" : "s");
else
value = value[..index] + value[index..]
.Replace("%s%", word.EndsWith('s') ? "" : "s");
}
value = value.Replace("%s%", "s");
// We have to do this chicanery due to support colors in the string
value = handleTrailingS(value);
return value;
}
private static string handleTrailingS(string value) {
var trailingIndex = -1;
while ((trailingIndex =
value.IndexOf("'s", trailingIndex + 1, StringComparison.Ordinal)) != -1) {
var startingWordBoundary = value[..trailingIndex].LastIndexOf(' ');
if (startingWordBoundary == -1
|| startingWordBoundary + 2 > value.Length) {
if (value.EndsWith("s's")) value = value[..^1];
break;
}
var endingWordBoundary = value.IndexOf(' ', trailingIndex + 2);
var word = value[(startingWordBoundary + 1)..endingWordBoundary];
var filteredWord = word.Where(c => char.IsLetterOrDigit(c) || c == '\'')
.ToArray();
if (new string(filteredWord).EndsWith("s's",
StringComparison.OrdinalIgnoreCase))
value = value[..(trailingIndex + 1)] + " "
+ value[(trailingIndex + 4)..];
}
return value;
}
public static string HandleAn(string value) {
var anMatches = anRegex().Matches(value);
foreach (Match match in anMatches) {
var anMatch = match.Value[1..^1];
var index = match.Index;
var prefix = value[..index];
var suffix = value[(index + match.Length)..];
// Determine if the next word starts with a vowel sound
var nextChar = char.ToLower(suffix.FirstOrDefault(char.IsLetterOrDigit));
value = nextChar switch {
'a' or 'e' or 'i' or 'o' or 'u' => prefix + anMatch + suffix,
_ => prefix + anMatch[0] + suffix
};
}
return value;
}
}

View File

@@ -1 +1,58 @@
# TTT
# TTT | [![ReadMe](https://img.shields.io/badge/ReadMe-018EF5?logo=readme&logoColor=fff&style=for-the-badge)](./TTT/README.md)
![Code Coverage](https://img.shields.io/endpoint?url=https://gist.githubusercontent.com/MSWS/6289e1f34da3b70fbba5f84f5ffb25a1/raw/code-coverage.json)
[![Discord](https://img.shields.io/discord/623439460683481091?style=for-the-badge&logo=discord&label=Discord)](https://msws.xyz/s/discord)
![Endpoint Badge](https://img.shields.io/endpoint?url=https%3A%2F%2Fwaka.msws.xyz%2Fapi%2Fcompat%2Fshields%2Fv1%2Fmsws%2Fproject%3ATTT%2Finterval%3Aall_time%26label%3DAll%2520time%26color%3Dblue&style=for-the-badge&label=Dev%20Time)
TTT (Trouble in Terrorist Town) is a game mode similar to Among Us where a group of players are attempting to
survive while eliminating the traitors among them.
## Features
- [X] Unit Testing
- [X] Basic Gameplay
- [X] Traitors
- [X] Detectives
- [X] Innocents
- [ ] Shop
- [ ] Karma
- [ ] Statistics
## Versioning
This project adheres to [Semantic Versioning 2.0.0](https://semver.org/spec/v2.0.0.html).
The versioning scheme consists of three components:
- **MAJOR** version indicates incompatible API changes,
- **MINOR** version signifies the addition of functionality in a backwards-compatible manner, and
- **PATCH** version reflects backwards-compatible bug fixes.
# Modules
### [TTT](./TTT)
You likely want to read the [TTT README](./TTT/README.md), which covers the structure of its own directory.
### [Versioning](./Versioning)
To allow for `MSBuild.GitVersion` to be used on both Windows and Linux (specifically NixOS), this project manually
converts `dotnet-gitversion` to the `GitVersionInformation` that is used.
### [Locale](./Locale)
Due to this project being primarily developed with Counter-Strike 2 (and more
specifically, [CounterStrikeSharp](https://github.com/roflmuffin/CounterStrikeSharp)) in mind, localization has been
built with flat-file storage based around YML/JSON.
In short, we write our locales in `en.yml`, run `Locale.csproj` to convert and combine all `**/Lang/en.yml` into a master
`lang/en.json`, and then run our tests / release pipelines with it.
It is recommend to read the [Locale README](./Locale/README.md) for more information on how to use it.
## Development
1. `git clone ...`
2. `dotnet restore`
3. `dotnet build`
4. Convert all `lang/en.yml` -> `lang/en.json` (Required for testing, refer to [Locale](./Locale/README.md))
5. `dotnet test` (Optional)

View File

@@ -1,16 +0,0 @@
namespace TTT.Api.Events;
[AttributeUsage(AttributeTargets.Method)]
public class EventHandlerAttribute : Attribute {
public uint Priority => Events.Priority.PRIORITY_DEFAULT;
public bool IgnoreCanceled => false;
}
public static class Priority {
public const uint PRIORITY_VERY_HIGH = 20;
public const uint PRIORITY_HIGH = 40;
public const uint PRIORITY_NORMAL = 60;
public const uint PRIORITY_LOW = 80;
public const uint PRIORITY_VERY_LOW = 100;
public const uint PRIORITY_DEFAULT = 50;
}

View File

@@ -1,5 +0,0 @@
namespace TTT.Api.Events;
public interface ICancelableEvent {
public bool IsCanceled { get; }
}

View File

@@ -1,3 +0,0 @@
namespace TTT.Api.Events;
public interface IListener;

View File

@@ -1,15 +0,0 @@
namespace TTT.Api;
public interface IAction {
IPlayer Player { get; }
IPlayer? Target { get; }
string Id { get; }
string Verb { get; }
string Details { get; }
string Format() {
return Target is not null ?
$"{Player} {Verb} {Target} {Details}" :
$"{Player} {Verb} {Details}";
}
}

View File

@@ -1,8 +0,0 @@
namespace TTT.Api;
public interface IGame {
ICollection<IPlayer> Players { get; }
DateTime StartedAt { get; }
DateTime? FinishedAt { get; }
IList<IAction> Actions { get; }
}

View File

@@ -1,11 +0,0 @@
namespace TTT.Api;
public interface IMessenger {
/// <summary>
/// Attempt to send a message to a player.
/// </summary>
/// <param name="player">The player to send the message to.</param>
/// <param name="message">The message to send</param>
/// <typeparam name="T"></typeparam>
Task<bool> Message(IPlayer player, string message);
}

View File

@@ -1,13 +0,0 @@
namespace TTT.Api;
public interface IOnlineMessenger : IMessenger {
Task<bool> IMessenger.Message(IPlayer player, string message) {
if (player is not IOnlinePlayer onlinePlayer)
return
Task.FromResult(false); // Cannot send message to non-online players
return Message(onlinePlayer, message);
}
Task<bool> Message(IOnlinePlayer player, string message);
}

View File

@@ -1,5 +0,0 @@
namespace TTT.Api;
public interface IOnlinePlayer : IPlayer {
ICollection<IRole> Roles { get; }
}

View File

@@ -1,11 +0,0 @@
namespace TTT.Api;
public interface IPlayer {
/// <summary>
/// The unique identifier for the player, should
/// be unique across all players at all times.
/// </summary>
string Id { get; }
string Name { get; }
}

View File

@@ -1,18 +0,0 @@
using System.Drawing;
namespace TTT.Api;
/// <summary>
/// Represents a role that can be assigned to a player.
/// Does not necessarily imply they are in the game.
/// </summary>
public interface IRole {
string Id { get; }
string Name { get; }
Color Color { get; }
bool ConflictsWith(IRole other) => false;
bool RequiresRole(IRole other) => false;
T? FindPlayerToAssign<T>(T player);
}

View File

@@ -1,8 +0,0 @@
using GitVersion;
namespace TTT.Api;
public interface ITerrorApi : ITerrorModule {
string ITerrorModule.Name => "Core";
string ITerrorModule.Version => GitVersionInformation.FullSemVer;
}

View File

@@ -1,6 +0,0 @@
namespace TTT.Api;
public interface ITerrorModule : IDisposable {
string Name { get; }
string Version { get; }
}

View File

@@ -1,10 +0,0 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>net8.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
</PropertyGroup>
<ItemGroup>
<Compile Include="..\GitVersionInformation.g.cs"/>
</ItemGroup>
</Project>

View File

@@ -1,4 +0,0 @@
// <autogenerated />
using System;
using System.Reflection;
[assembly: global::System.Runtime.Versioning.TargetFrameworkAttribute(".NETCoreApp,Version=v8.0", FrameworkDisplayName = ".NET 8.0")]

View File

@@ -1,22 +0,0 @@
//------------------------------------------------------------------------------
// <auto-generated>
// This code was generated by a tool.
//
// Changes to this file may cause incorrect behavior and will be lost if
// the code is regenerated.
// </auto-generated>
//------------------------------------------------------------------------------
using System;
using System.Reflection;
[assembly: System.Reflection.AssemblyCompanyAttribute("TTT.Api")]
[assembly: System.Reflection.AssemblyConfigurationAttribute("Debug")]
[assembly: System.Reflection.AssemblyFileVersionAttribute("1.0.0.0")]
[assembly: System.Reflection.AssemblyInformationalVersionAttribute("1.0.0")]
[assembly: System.Reflection.AssemblyProductAttribute("TTT.Api")]
[assembly: System.Reflection.AssemblyTitleAttribute("TTT.Api")]
[assembly: System.Reflection.AssemblyVersionAttribute("1.0.0.0")]
// Generated by the MSBuild WriteCodeFragment class.

View File

@@ -1 +0,0 @@
cdbc441e8749481d9af8e6fbd6ae33eb767c505116c17e79b097343c67721cbf

View File

@@ -1,13 +0,0 @@
is_global = true
build_property.TargetFramework = net8.0
build_property.TargetPlatformMinVersion =
build_property.UsingMicrosoftNETSdkWeb =
build_property.ProjectTypeGuids =
build_property.InvariantGlobalization =
build_property.PlatformNeutralAssembly =
build_property.EnforceExtendedAnalyzerRules =
build_property._SupportedPlatformList = Linux,macOS,Windows
build_property.RootNamespace = TTT.Api
build_property.ProjectDir = /home/iboaz/Documents/Coding/ego/s2/TTT/TTT.Api/
build_property.EnableComHosting =
build_property.EnableGeneratedComInterfaceComImportInterop =

View File

@@ -1,8 +0,0 @@
// <auto-generated/>
global using global::System;
global using global::System.Collections.Generic;
global using global::System.IO;
global using global::System.Linq;
global using global::System.Net.Http;
global using global::System.Threading;
global using global::System.Threading.Tasks;

View File

@@ -1,66 +0,0 @@
{
"format": 1,
"restore": {
"/home/iboaz/Documents/Coding/ego/s2/TTT/TTT.Api/TTT.Api.csproj": {}
},
"projects": {
"/home/iboaz/Documents/Coding/ego/s2/TTT/TTT.Api/TTT.Api.csproj": {
"version": "1.0.0",
"restore": {
"projectUniqueName": "/home/iboaz/Documents/Coding/ego/s2/TTT/TTT.Api/TTT.Api.csproj",
"projectName": "TTT.Api",
"projectPath": "/home/iboaz/Documents/Coding/ego/s2/TTT/TTT.Api/TTT.Api.csproj",
"packagesPath": "/home/iboaz/.nuget/packages/",
"outputPath": "/home/iboaz/Documents/Coding/ego/s2/TTT/TTT.Api/obj/",
"projectStyle": "PackageReference",
"configFilePaths": [
"/home/iboaz/.nuget/NuGet/NuGet.Config"
],
"originalTargetFrameworks": [
"net8.0"
],
"sources": {
"https://api.nuget.org/v3/index.json": {}
},
"frameworks": {
"net8.0": {
"targetAlias": "net8.0",
"projectReferences": {}
}
},
"warningProperties": {
"warnAsError": [
"NU1605"
]
},
"restoreAuditProperties": {
"enableAudit": "true",
"auditLevel": "low",
"auditMode": "direct"
}
},
"frameworks": {
"net8.0": {
"targetAlias": "net8.0",
"imports": [
"net461",
"net462",
"net47",
"net471",
"net472",
"net48",
"net481"
],
"assetTargetFallback": true,
"warn": true,
"frameworkReferences": {
"Microsoft.NETCore.App": {
"privateAssets": "all"
}
},
"runtimeIdentifierGraphPath": "/nix/store/1d8g8d8xrrlxwfgbavgl4snymznfw5r7-dotnet-sdk-8.0.412/share/dotnet/sdk/8.0.412/PortableRuntimeIdentifierGraph.json"
}
}
}
}
}

View File

@@ -1,15 +0,0 @@
<?xml version="1.0" encoding="utf-8" standalone="no"?>
<Project ToolsVersion="14.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup Condition=" '$(ExcludeRestorePackageImports)' != 'true' ">
<RestoreSuccess Condition=" '$(RestoreSuccess)' == '' ">True</RestoreSuccess>
<RestoreTool Condition=" '$(RestoreTool)' == '' ">NuGet</RestoreTool>
<ProjectAssetsFile Condition=" '$(ProjectAssetsFile)' == '' ">$(MSBuildThisFileDirectory)project.assets.json</ProjectAssetsFile>
<NuGetPackageRoot Condition=" '$(NuGetPackageRoot)' == '' ">/home/iboaz/.nuget/packages/</NuGetPackageRoot>
<NuGetPackageFolders Condition=" '$(NuGetPackageFolders)' == '' ">/home/iboaz/.nuget/packages/</NuGetPackageFolders>
<NuGetProjectStyle Condition=" '$(NuGetProjectStyle)' == '' ">PackageReference</NuGetProjectStyle>
<NuGetToolVersion Condition=" '$(NuGetToolVersion)' == '' ">6.13.2</NuGetToolVersion>
</PropertyGroup>
<ItemGroup Condition=" '$(ExcludeRestorePackageImports)' != 'true' ">
<SourceRoot Include="/home/iboaz/.nuget/packages/" />
</ItemGroup>
</Project>

View File

@@ -1,2 +0,0 @@
<?xml version="1.0" encoding="utf-8" standalone="no"?>
<Project ToolsVersion="14.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003" />

View File

@@ -1,71 +0,0 @@
{
"version": 3,
"targets": {
"net8.0": {}
},
"libraries": {},
"projectFileDependencyGroups": {
"net8.0": []
},
"packageFolders": {
"/home/iboaz/.nuget/packages/": {}
},
"project": {
"version": "1.0.0",
"restore": {
"projectUniqueName": "/home/iboaz/Documents/Coding/ego/s2/TTT/TTT.Api/TTT.Api.csproj",
"projectName": "TTT.Api",
"projectPath": "/home/iboaz/Documents/Coding/ego/s2/TTT/TTT.Api/TTT.Api.csproj",
"packagesPath": "/home/iboaz/.nuget/packages/",
"outputPath": "/home/iboaz/Documents/Coding/ego/s2/TTT/TTT.Api/obj/",
"projectStyle": "PackageReference",
"configFilePaths": [
"/home/iboaz/.nuget/NuGet/NuGet.Config"
],
"originalTargetFrameworks": [
"net8.0"
],
"sources": {
"https://api.nuget.org/v3/index.json": {}
},
"frameworks": {
"net8.0": {
"targetAlias": "net8.0",
"projectReferences": {}
}
},
"warningProperties": {
"warnAsError": [
"NU1605"
]
},
"restoreAuditProperties": {
"enableAudit": "true",
"auditLevel": "low",
"auditMode": "direct"
}
},
"frameworks": {
"net8.0": {
"targetAlias": "net8.0",
"imports": [
"net461",
"net462",
"net47",
"net471",
"net472",
"net48",
"net481"
],
"assetTargetFallback": true,
"warn": true,
"frameworkReferences": {
"Microsoft.NETCore.App": {
"privateAssets": "all"
}
},
"runtimeIdentifierGraphPath": "/nix/store/1d8g8d8xrrlxwfgbavgl4snymznfw5r7-dotnet-sdk-8.0.412/share/dotnet/sdk/8.0.412/PortableRuntimeIdentifierGraph.json"
}
}
}
}

View File

@@ -1,8 +0,0 @@
{
"version": 2,
"dgSpecHash": "zHAlCbUQsJw=",
"success": true,
"projectFilePath": "/home/iboaz/Documents/Coding/ego/s2/TTT/TTT.Api/TTT.Api.csproj",
"expectedPackageFiles": [],
"logs": []
}

View File

@@ -1 +0,0 @@
"restore":{"projectUniqueName":"/home/iboaz/Documents/Coding/ego/s2/TTT/TTT.Api/TTT.Api.csproj","projectName":"TTT.Api","projectPath":"/home/iboaz/Documents/Coding/ego/s2/TTT/TTT.Api/TTT.Api.csproj","outputPath":"/home/iboaz/Documents/Coding/ego/s2/TTT/TTT.Api/obj/","projectStyle":"PackageReference","originalTargetFrameworks":["net8.0"],"sources":{"https://api.nuget.org/v3/index.json":{}},"frameworks":{"net8.0":{"targetAlias":"net8.0","projectReferences":{}}},"warningProperties":{"warnAsError":["NU1605"]},"restoreAuditProperties":{"enableAudit":"true","auditLevel":"low","auditMode":"direct"}}"frameworks":{"net8.0":{"targetAlias":"net8.0","imports":["net461","net462","net47","net471","net472","net48","net481"],"assetTargetFallback":true,"warn":true,"frameworkReferences":{"Microsoft.NETCore.App":{"privateAssets":"all"}},"runtimeIdentifierGraphPath":"/nix/store/1d8g8d8xrrlxwfgbavgl4snymznfw5r7-dotnet-sdk-8.0.412/share/dotnet/sdk/8.0.412/PortableRuntimeIdentifierGraph.json"}}

View File

@@ -1 +0,0 @@
17536984184998885

View File

@@ -1 +0,0 @@
17536985896526724

Submodule TTT.Core deleted from e0f4501475

78
TTT.sln Normal file
View File

@@ -0,0 +1,78 @@

Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio Version 17
VisualStudioVersion = 17.0.31903.59
MinimumVisualStudioVersion = 10.0.40219.1
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "API", "TTT\API\API.csproj", "{A7B58A1F-7C15-423B-B008-30E38D0E2135}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Plugin", "TTT\Plugin\Plugin.csproj", "{581DA648-28A9-4E6F-9E1C-7DD19B90C10F}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Test", "TTT\Test\Test.csproj", "{D0424929-808F-49F8-9894-DDD770F55B7C}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "CS2", "TTT\CS2\CS2.csproj", "{A595E6E3-A881-4524-8E5D-DE65106E1DD5}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Game", "TTT\Game\Game.csproj", "{C41F5E15-2E28-4D14-A9F8-06FEADD24F2D}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Versioning", "Versioning\Versioning.csproj", "{7AABCDC7-14BE-437C-BD41-C765CAB82F0E}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Locale", "Locale\Locale.csproj", "{B5F91489-CD1B-42F2-9CF0-889604BD7C7E}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Shop", "TTT\Shop\Shop.csproj", "{478416D7-4996-41CC-BDDF-5BF50B505D0F}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Karma", "TTT\Karma\Karma.csproj", "{AFC791EC-750C-423F-9F35-87636657E990}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ShopAPI", "TTT\ShopAPI\ShopAPI.csproj", "{16F720B5-9D45-47BF-8C80-4F91005E36D1}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
Release|Any CPU = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{A7B58A1F-7C15-423B-B008-30E38D0E2135}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{A7B58A1F-7C15-423B-B008-30E38D0E2135}.Debug|Any CPU.Build.0 = Debug|Any CPU
{A7B58A1F-7C15-423B-B008-30E38D0E2135}.Release|Any CPU.ActiveCfg = Release|Any CPU
{A7B58A1F-7C15-423B-B008-30E38D0E2135}.Release|Any CPU.Build.0 = Release|Any CPU
{581DA648-28A9-4E6F-9E1C-7DD19B90C10F}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{581DA648-28A9-4E6F-9E1C-7DD19B90C10F}.Debug|Any CPU.Build.0 = Debug|Any CPU
{581DA648-28A9-4E6F-9E1C-7DD19B90C10F}.Release|Any CPU.ActiveCfg = Release|Any CPU
{581DA648-28A9-4E6F-9E1C-7DD19B90C10F}.Release|Any CPU.Build.0 = Release|Any CPU
{D0424929-808F-49F8-9894-DDD770F55B7C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{D0424929-808F-49F8-9894-DDD770F55B7C}.Debug|Any CPU.Build.0 = Debug|Any CPU
{D0424929-808F-49F8-9894-DDD770F55B7C}.Release|Any CPU.ActiveCfg = Release|Any CPU
{D0424929-808F-49F8-9894-DDD770F55B7C}.Release|Any CPU.Build.0 = Release|Any CPU
{A595E6E3-A881-4524-8E5D-DE65106E1DD5}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{A595E6E3-A881-4524-8E5D-DE65106E1DD5}.Debug|Any CPU.Build.0 = Debug|Any CPU
{A595E6E3-A881-4524-8E5D-DE65106E1DD5}.Release|Any CPU.ActiveCfg = Release|Any CPU
{A595E6E3-A881-4524-8E5D-DE65106E1DD5}.Release|Any CPU.Build.0 = Release|Any CPU
{C41F5E15-2E28-4D14-A9F8-06FEADD24F2D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{C41F5E15-2E28-4D14-A9F8-06FEADD24F2D}.Debug|Any CPU.Build.0 = Debug|Any CPU
{C41F5E15-2E28-4D14-A9F8-06FEADD24F2D}.Release|Any CPU.ActiveCfg = Release|Any CPU
{C41F5E15-2E28-4D14-A9F8-06FEADD24F2D}.Release|Any CPU.Build.0 = Release|Any CPU
{7AABCDC7-14BE-437C-BD41-C765CAB82F0E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{7AABCDC7-14BE-437C-BD41-C765CAB82F0E}.Debug|Any CPU.Build.0 = Debug|Any CPU
{7AABCDC7-14BE-437C-BD41-C765CAB82F0E}.Release|Any CPU.ActiveCfg = Release|Any CPU
{7AABCDC7-14BE-437C-BD41-C765CAB82F0E}.Release|Any CPU.Build.0 = Release|Any CPU
{B5F91489-CD1B-42F2-9CF0-889604BD7C7E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{B5F91489-CD1B-42F2-9CF0-889604BD7C7E}.Debug|Any CPU.Build.0 = Debug|Any CPU
{B5F91489-CD1B-42F2-9CF0-889604BD7C7E}.Release|Any CPU.ActiveCfg = Release|Any CPU
{B5F91489-CD1B-42F2-9CF0-889604BD7C7E}.Release|Any CPU.Build.0 = Release|Any CPU
{478416D7-4996-41CC-BDDF-5BF50B505D0F}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{478416D7-4996-41CC-BDDF-5BF50B505D0F}.Debug|Any CPU.Build.0 = Debug|Any CPU
{478416D7-4996-41CC-BDDF-5BF50B505D0F}.Release|Any CPU.ActiveCfg = Release|Any CPU
{478416D7-4996-41CC-BDDF-5BF50B505D0F}.Release|Any CPU.Build.0 = Release|Any CPU
{AFC791EC-750C-423F-9F35-87636657E990}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{AFC791EC-750C-423F-9F35-87636657E990}.Debug|Any CPU.Build.0 = Debug|Any CPU
{AFC791EC-750C-423F-9F35-87636657E990}.Release|Any CPU.ActiveCfg = Release|Any CPU
{AFC791EC-750C-423F-9F35-87636657E990}.Release|Any CPU.Build.0 = Release|Any CPU
{16F720B5-9D45-47BF-8C80-4F91005E36D1}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{16F720B5-9D45-47BF-8C80-4F91005E36D1}.Debug|Any CPU.Build.0 = Debug|Any CPU
{16F720B5-9D45-47BF-8C80-4F91005E36D1}.Release|Any CPU.ActiveCfg = Release|Any CPU
{16F720B5-9D45-47BF-8C80-4F91005E36D1}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(NestedProjects) = preSolution
EndGlobalSection
EndGlobal

156
TTT.sln.DotSettings Normal file
View File

@@ -0,0 +1,156 @@
<wpf:ResourceDictionary xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:s="clr-namespace:System;assembly=mscorlib"
xmlns:wpf="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xml:space="preserve">
<s:String x:Key="/Default/CodeInspection/Highlighting/InspectionSeverities/=InconsistentNaming/@EntryIndexedValue">DO_NOT_SHOW</s:String>
<s:String x:Key="/Default/CodeStyle/CodeCleanup/RecentlyUsedProfile/@EntryValue">Built-in: Full Cleanup</s:String>
<s:String x:Key="/Default/CodeStyle/CodeFormatting/CSharpCodeStyle/MODIFIERS_ORDER/@EntryValue">public private override virtual file new abstract internal protected sealed static readonly extern unsafe volatile async required</s:String>
<s:String
x:Key="/Default/CodeStyle/CodeFormatting/CSharpCodeStyle/PARENTHESES_REDUNDANCY_STYLE/@EntryValue">Remove</s:String>
<s:String
x:Key="/Default/CodeStyle/CodeFormatting/CSharpCodeStyle/ThisQualifier/INSTANCE_MEMBERS_QUALIFY_DECLARED_IN/@EntryValue">0</s:String>
<s:String
x:Key="/Default/CodeStyle/CodeFormatting/CSharpFormat/ACCESSOR_DECLARATION_BRACES/@EntryValue">END_OF_LINE</s:String>
<s:String x:Key="/Default/CodeStyle/CodeFormatting/CSharpFormat/ACCESSOR_OWNER_DECLARATION_BRACES/@EntryValue">END_OF_LINE</s:String>
<s:Boolean
x:Key="/Default/CodeStyle/CodeFormatting/CSharpFormat/ALIGN_MULTILINE_BINARY_EXPRESSIONS_CHAIN/@EntryValue">False</s:Boolean>
<s:Boolean x:Key="/Default/CodeStyle/CodeFormatting/CSharpFormat/ALIGN_MULTILINE_STATEMENT_CONDITIONS/@EntryValue">False</s:Boolean>
<s:Boolean
x:Key="/Default/CodeStyle/CodeFormatting/CSharpFormat/ALLOW_COMMENT_AFTER_LBRACE/@EntryValue">True</s:Boolean>
<s:String x:Key="/Default/CodeStyle/CodeFormatting/CSharpFormat/ANONYMOUS_METHOD_DECLARATION_BRACES/@EntryValue">END_OF_LINE</s:String>
<s:String x:Key="/Default/CodeStyle/CodeFormatting/CSharpFormat/CASE_BLOCK_BRACES/@EntryValue">END_OF_LINE</s:String>
<s:String
x:Key="/Default/CodeStyle/CodeFormatting/CSharpFormat/EMPTY_BLOCK_STYLE/@EntryValue">TOGETHER_SAME_LINE</s:String>
<s:Boolean
x:Key="/Default/CodeStyle/CodeFormatting/CSharpFormat/INDENT_BRACES_INSIDE_STATEMENT_CONDITIONS/@EntryValue">False</s:Boolean>
<s:Boolean
x:Key="/Default/CodeStyle/CodeFormatting/CSharpFormat/INDENT_NESTED_FIXED_STMT/@EntryValue">True</s:Boolean>
<s:Boolean x:Key="/Default/CodeStyle/CodeFormatting/CSharpFormat/INDENT_NESTED_FOR_STMT/@EntryValue">True</s:Boolean>
<s:Boolean
x:Key="/Default/CodeStyle/CodeFormatting/CSharpFormat/INDENT_NESTED_FOREACH_STMT/@EntryValue">True</s:Boolean>
<s:Boolean x:Key="/Default/CodeStyle/CodeFormatting/CSharpFormat/INDENT_NESTED_LOCK_STMT/@EntryValue">True</s:Boolean>
<s:Boolean
x:Key="/Default/CodeStyle/CodeFormatting/CSharpFormat/INDENT_NESTED_USINGS_STMT/@EntryValue">True</s:Boolean>
<s:Boolean
x:Key="/Default/CodeStyle/CodeFormatting/CSharpFormat/INDENT_NESTED_WHILE_STMT/@EntryValue">True</s:Boolean>
<s:String
x:Key="/Default/CodeStyle/CodeFormatting/CSharpFormat/INDENT_RAW_LITERAL_STRING/@EntryValue">INDENT</s:String>
<s:Int64 x:Key="/Default/CodeStyle/CodeFormatting/CSharpFormat/INDENT_SIZE/@EntryValue">2</s:Int64>
<s:String x:Key="/Default/CodeStyle/CodeFormatting/CSharpFormat/INITIALIZER_BRACES/@EntryValue">END_OF_LINE</s:String>
<s:Boolean x:Key="/Default/CodeStyle/CodeFormatting/CSharpFormat/INT_ALIGN_ASSIGNMENTS/@EntryValue">True</s:Boolean>
<s:Boolean x:Key="/Default/CodeStyle/CodeFormatting/CSharpFormat/INT_ALIGN_COMMENTS/@EntryValue">True</s:Boolean>
<s:Boolean
x:Key="/Default/CodeStyle/CodeFormatting/CSharpFormat/INT_ALIGN_PROPERTY_PATTERNS/@EntryValue">True</s:Boolean>
<s:Boolean
x:Key="/Default/CodeStyle/CodeFormatting/CSharpFormat/INT_ALIGN_SWITCH_EXPRESSIONS/@EntryValue">True</s:Boolean>
<s:Boolean
x:Key="/Default/CodeStyle/CodeFormatting/CSharpFormat/INT_ALIGN_SWITCH_SECTIONS/@EntryValue">True</s:Boolean>
<s:Boolean x:Key="/Default/CodeStyle/CodeFormatting/CSharpFormat/INT_ALIGN_VARIABLES/@EntryValue">True</s:Boolean>
<s:String
x:Key="/Default/CodeStyle/CodeFormatting/CSharpFormat/INVOCABLE_DECLARATION_BRACES/@EntryValue">END_OF_LINE</s:String>
<s:Boolean
x:Key="/Default/CodeStyle/CodeFormatting/CSharpFormat/KEEP_EXISTING_DECLARATION_PARENS_ARRANGEMENT/@EntryValue">False</s:Boolean>
<s:Boolean
x:Key="/Default/CodeStyle/CodeFormatting/CSharpFormat/KEEP_EXISTING_EMBEDDED_ARRANGEMENT/@EntryValue">False</s:Boolean>
<s:Boolean x:Key="/Default/CodeStyle/CodeFormatting/CSharpFormat/KEEP_EXISTING_EXPR_MEMBER_ARRANGEMENT/@EntryValue">False</s:Boolean>
<s:Boolean x:Key="/Default/CodeStyle/CodeFormatting/CSharpFormat/KEEP_EXISTING_INITIALIZER_ARRANGEMENT/@EntryValue">False</s:Boolean>
<s:Boolean
x:Key="/Default/CodeStyle/CodeFormatting/CSharpFormat/KEEP_EXISTING_INVOCATION_PARENS_ARRANGEMENT/@EntryValue">False</s:Boolean>
<s:Boolean x:Key="/Default/CodeStyle/CodeFormatting/CSharpFormat/KEEP_EXISTING_LIST_PATTERNS_ARRANGEMENT/@EntryValue">False</s:Boolean>
<s:Boolean
x:Key="/Default/CodeStyle/CodeFormatting/CSharpFormat/KEEP_EXISTING_PRIMARY_CONSTRUCTOR_DECLARATION_PARENS_ARRANGEMENT/@EntryValue">False</s:Boolean>
<s:Boolean
x:Key="/Default/CodeStyle/CodeFormatting/CSharpFormat/KEEP_EXISTING_PROPERTY_PATTERNS_ARRANGEMENT/@EntryValue">False</s:Boolean>
<s:Boolean x:Key="/Default/CodeStyle/CodeFormatting/CSharpFormat/KEEP_USER_LINEBREAKS/@EntryValue">False</s:Boolean>
<s:Int64
x:Key="/Default/CodeStyle/CodeFormatting/CSharpFormat/MAX_ARRAY_INITIALIZER_ELEMENTS_ON_LINE/@EntryValue">10</s:Int64>
<s:Int64 x:Key="/Default/CodeStyle/CodeFormatting/CSharpFormat/MAX_ENUM_MEMBERS_ON_LINE/@EntryValue">5</s:Int64>
<s:Int64 x:Key="/Default/CodeStyle/CodeFormatting/CSharpFormat/MAX_FORMAL_PARAMETERS_ON_LINE/@EntryValue">5</s:Int64>
<s:Int64
x:Key="/Default/CodeStyle/CodeFormatting/CSharpFormat/MAX_INVOCATION_ARGUMENTS_ON_LINE/@EntryValue">10</s:Int64>
<s:Int64
x:Key="/Default/CodeStyle/CodeFormatting/CSharpFormat/MAX_PRIMARY_CONSTRUCTOR_PARAMETERS_ON_LINE/@EntryValue">5</s:Int64>
<s:String x:Key="/Default/CodeStyle/CodeFormatting/CSharpFormat/NESTED_TERNARY_STYLE/@EntryValue">COMPACT</s:String>
<s:String x:Key="/Default/CodeStyle/CodeFormatting/CSharpFormat/OTHER_BRACES/@EntryValue">END_OF_LINE</s:String>
<s:Boolean x:Key="/Default/CodeStyle/CodeFormatting/CSharpFormat/OUTDENT_DOTS/@EntryValue">True</s:Boolean>
<s:Boolean
x:Key="/Default/CodeStyle/CodeFormatting/CSharpFormat/OUTDENT_STATEMENT_LABELS/@EntryValue">True</s:Boolean>
<s:String x:Key="/Default/CodeStyle/CodeFormatting/CSharpFormat/PLACE_ACCESSOR_ATTRIBUTE_ON_SAME_LINE_EX/@EntryValue">NEVER</s:String>
<s:String
x:Key="/Default/CodeStyle/CodeFormatting/CSharpFormat/PLACE_ACCESSORHOLDER_ATTRIBUTE_ON_SAME_LINE_EX/@EntryValue">NEVER</s:String>
<s:Boolean
x:Key="/Default/CodeStyle/CodeFormatting/CSharpFormat/PLACE_CATCH_ON_NEW_LINE/@EntryValue">False</s:Boolean>
<s:Boolean x:Key="/Default/CodeStyle/CodeFormatting/CSharpFormat/PLACE_ELSE_ON_NEW_LINE/@EntryValue">False</s:Boolean>
<s:String x:Key="/Default/CodeStyle/CodeFormatting/CSharpFormat/PLACE_FIELD_ATTRIBUTE_ON_SAME_LINE_EX/@EntryValue">NEVER</s:String>
<s:Boolean
x:Key="/Default/CodeStyle/CodeFormatting/CSharpFormat/PLACE_FINALLY_ON_NEW_LINE/@EntryValue">False</s:Boolean>
<s:Boolean
x:Key="/Default/CodeStyle/CodeFormatting/CSharpFormat/PLACE_LINQ_INTO_ON_NEW_LINE/@EntryValue">False</s:Boolean>
<s:String
x:Key="/Default/CodeStyle/CodeFormatting/CSharpFormat/PLACE_RECORD_FIELD_ATTRIBUTE_ON_SAME_LINE_EX/@EntryValue">NEVER</s:String>
<s:Boolean
x:Key="/Default/CodeStyle/CodeFormatting/CSharpFormat/PLACE_SIMPLE_EMBEDDED_BLOCK_ON_SAME_LINE/@EntryValue">True</s:Boolean>
<s:Boolean
x:Key="/Default/CodeStyle/CodeFormatting/CSharpFormat/PLACE_SIMPLE_METHOD_ON_SINGLE_LINE/@EntryValue">True</s:Boolean>
<s:Boolean
x:Key="/Default/CodeStyle/CodeFormatting/CSharpFormat/PLACE_SIMPLE_SWITCH_EXPRESSION_ON_SINGLE_LINE/@EntryValue">True</s:Boolean>
<s:Boolean x:Key="/Default/CodeStyle/CodeFormatting/CSharpFormat/STICK_COMMENT/@EntryValue">False</s:Boolean>
<s:Int64 x:Key="/Default/CodeStyle/CodeFormatting/CSharpFormat/TAB_WIDTH/@EntryValue">2</s:Int64>
<s:String
x:Key="/Default/CodeStyle/CodeFormatting/CSharpFormat/TYPE_DECLARATION_BRACES/@EntryValue">END_OF_LINE</s:String>
<s:Boolean
x:Key="/Default/CodeStyle/CodeFormatting/CSharpFormat/WRAP_AFTER_PRIMARY_CONSTRUCTOR_DECLARATION_LPAR/@EntryValue">False</s:Boolean>
<s:Boolean
x:Key="/Default/CodeStyle/CodeFormatting/CSharpFormat/WRAP_BEFORE_ARROW_WITH_EXPRESSIONS/@EntryValue">True</s:Boolean>
<s:Boolean
x:Key="/Default/CodeStyle/CodeFormatting/CSharpFormat/WRAP_BEFORE_BINARY_OPSIGN/@EntryValue">True</s:Boolean>
<s:Boolean
x:Key="/Default/CodeStyle/CodeFormatting/CSharpFormat/WRAP_BEFORE_TERNARY_OPSIGNS/@EntryValue">False</s:Boolean>
<s:String
x:Key="/Default/CodeStyle/CodeFormatting/CSharpFormat/WRAP_CHAINED_METHOD_CALLS/@EntryValue">CHOP_IF_LONG</s:String>
<s:String
x:Key="/Default/CodeStyle/CodeFormatting/CSharpFormat/WRAP_ENUM_DECLARATION/@EntryValue">CHOP_IF_LONG</s:String>
<s:String
x:Key="/Default/CodeStyle/CodeFormatting/CSharpFormat/WRAP_FOR_STMT_HEADER_STYLE/@EntryValue">WRAP_IF_LONG</s:String>
<s:Int64 x:Key="/Default/CodeStyle/CodeFormatting/CSharpFormat/WRAP_LIMIT/@EntryValue">80</s:Int64>
<s:String
x:Key="/Default/CodeStyle/CodeFormatting/CSharpFormat/WRAP_PRIMARY_CONSTRUCTOR_PARAMETERS_STYLE/@EntryValue">WRAP_IF_LONG</s:String>
<s:Boolean x:Key="/Default/CodeStyle/Naming/CSharpAutoNaming/IsNotificationDisabled/@EntryValue">True</s:Boolean>
<s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/Abbreviations/=API/@EntryIndexedValue">API</s:String>
<s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/Abbreviations/=IO/@EntryIndexedValue">IO</s:String>
<s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/Abbreviations/=LG/@EntryIndexedValue">LG</s:String>
<s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/Abbreviations/=LR/@EntryIndexedValue">LR</s:String>
<s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/Abbreviations/=ST/@EntryIndexedValue">ST</s:String>
<s:String
x:Key="/Default/CodeStyle/Naming/CSharpNaming/UserRules/=08582792_002Dd334_002D4f6d_002Db467_002Dfc7b9fd4557b/@EntryIndexedValue">&lt;Policy&gt;&lt;Descriptor Staticness="Any" AccessRightKinds="Private, ProtectedInternal, Internal, PrivateProtected" Description="Non-Public Methods"&gt;&lt;ElementKinds&gt;&lt;Kind Name="METHOD" /&gt;&lt;/ElementKinds&gt;&lt;/Descriptor&gt;&lt;Policy Inspect="True" WarnAboutPrefixesAndSuffixes="False" Prefix="" Suffix="" Style="aaBb" /&gt;&lt;/Policy&gt;</s:String>
<s:String
x:Key="/Default/CodeStyle/Naming/CSharpNaming/UserRules/=15b5b1f1_002D457c_002D4ca6_002Db278_002D5615aedc07d3/@EntryIndexedValue">&lt;Policy&gt;&lt;Descriptor Staticness="Static" AccessRightKinds="Private" Description="Static readonly fields (private)"&gt;&lt;ElementKinds&gt;&lt;Kind Name="READONLY_FIELD" /&gt;&lt;/ElementKinds&gt;&lt;/Descriptor&gt;&lt;Policy Inspect="True" WarnAboutPrefixesAndSuffixes="False" Prefix="" Suffix="" Style="AA_BB" /&gt;&lt;/Policy&gt;</s:String>
<s:String
x:Key="/Default/CodeStyle/Naming/CSharpNaming/UserRules/=236f7aa5_002D7b06_002D43ca_002Dbf2a_002D9b31bfcff09a/@EntryIndexedValue">&lt;Policy&gt;&lt;Descriptor Staticness="Any" AccessRightKinds="Private" Description="Constant fields (private)"&gt;&lt;ElementKinds&gt;&lt;Kind Name="CONSTANT_FIELD" /&gt;&lt;/ElementKinds&gt;&lt;/Descriptor&gt;&lt;Policy Inspect="True" WarnAboutPrefixesAndSuffixes="False" Prefix="" Suffix="" Style="AA_BB" /&gt;&lt;/Policy&gt;</s:String>
<s:String
x:Key="/Default/CodeStyle/Naming/CSharpNaming/UserRules/=4a98fdf6_002D7d98_002D4f5a_002Dafeb_002Dea44ad98c70c/@EntryIndexedValue">&lt;Policy&gt;&lt;Descriptor Staticness="Instance" AccessRightKinds="Private" Description="Instance fields (private)"&gt;&lt;ElementKinds&gt;&lt;Kind Name="FIELD" /&gt;&lt;Kind Name="READONLY_FIELD" /&gt;&lt;/ElementKinds&gt;&lt;/Descriptor&gt;&lt;Policy Inspect="True" WarnAboutPrefixesAndSuffixes="False" Prefix="" Suffix="" Style="aaBb" /&gt;&lt;/Policy&gt;</s:String>
<s:String
x:Key="/Default/CodeStyle/Naming/CSharpNaming/UserRules/=669e5282_002Dfb4b_002D4e90_002D91e7_002D07d269d04b60/@EntryIndexedValue">&lt;Policy&gt;&lt;Descriptor Staticness="Any" AccessRightKinds="Protected, ProtectedInternal, Internal, Public, PrivateProtected" Description="Constant fields (not private)"&gt;&lt;ElementKinds&gt;&lt;Kind Name="CONSTANT_FIELD" /&gt;&lt;/ElementKinds&gt;&lt;/Descriptor&gt;&lt;Policy Inspect="True" WarnAboutPrefixesAndSuffixes="False" Prefix="" Suffix="" Style="AA_BB" /&gt;&lt;/Policy&gt;</s:String>
<s:String
x:Key="/Default/CodeStyle/Naming/CSharpNaming/UserRules/=8284009d_002De743_002D4d89_002D9402_002Da5bf9a89b657/@EntryIndexedValue">&lt;Policy&gt;&lt;Descriptor Staticness="Any" AccessRightKinds="Protected, Public, FileLocal" Description="Public Methods"&gt;&lt;ElementKinds&gt;&lt;Kind Name="METHOD" /&gt;&lt;/ElementKinds&gt;&lt;/Descriptor&gt;&lt;Policy Inspect="True" WarnAboutPrefixesAndSuffixes="False" Prefix="" Suffix="" Style="AaBb" /&gt;&lt;/Policy&gt;</s:String>
<s:String
x:Key="/Default/CodeStyle/Naming/CSharpNaming/UserRules/=8a85b61a_002D1024_002D4f87_002Db9ef_002D1fdae19930a1/@EntryIndexedValue">&lt;Policy&gt;&lt;Descriptor Staticness="Any" AccessRightKinds="Any" Description="Parameters"&gt;&lt;ElementKinds&gt;&lt;Kind Name="PARAMETER" /&gt;&lt;/ElementKinds&gt;&lt;/Descriptor&gt;&lt;Policy Inspect="True" WarnAboutPrefixesAndSuffixes="False" Prefix="" Suffix="" Style="aaBb"&gt;&lt;ExtraRule Prefix="_" Suffix="" Style="aaBb" /&gt;&lt;/Policy&gt;&lt;/Policy&gt;</s:String>
<s:String
x:Key="/Default/CodeStyle/Naming/CSharpNaming/UserRules/=8b8504e3_002Df0be_002D4c14_002D9103_002Dc732f2bddc15/@EntryIndexedValue">&lt;Policy&gt;&lt;Descriptor Staticness="Any" AccessRightKinds="Any" Description="Enum members"&gt;&lt;ElementKinds&gt;&lt;Kind Name="ENUM_MEMBER" /&gt;&lt;/ElementKinds&gt;&lt;/Descriptor&gt;&lt;Policy Inspect="True" WarnAboutPrefixesAndSuffixes="False" Prefix="" Suffix="" Style="AA_BB" /&gt;&lt;/Policy&gt;</s:String>
<s:String
x:Key="/Default/CodeStyle/Naming/CSharpNaming/UserRules/=c873eafb_002Dd57f_002D481d_002D8c93_002D77f6863c2f88/@EntryIndexedValue">&lt;Policy&gt;&lt;Descriptor Staticness="Static" AccessRightKinds="Protected, ProtectedInternal, Internal, Public, PrivateProtected" Description="Static readonly fields (not private)"&gt;&lt;ElementKinds&gt;&lt;Kind Name="READONLY_FIELD" /&gt;&lt;/ElementKinds&gt;&lt;/Descriptor&gt;&lt;Policy Inspect="True" WarnAboutPrefixesAndSuffixes="False" Prefix="" Suffix="" Style="AA_BB" /&gt;&lt;/Policy&gt;</s:String>
<s:Boolean
x:Key="/Default/Environment/Filtering/ExcludeCoverageFilters/=CS2_003B_002A_003B_002A_003B_002A/@EntryIndexedValue">True</s:Boolean>
<s:Boolean
x:Key="/Default/Environment/Filtering/ExcludeCoverageFilters/=Plugin_003B_002A_003B_002A_003B_002A/@EntryIndexedValue">True</s:Boolean>
<s:Boolean
x:Key="/Default/Environment/Filtering/ExcludeCoverageFilters/=TTT_003B_002A_003B_002A_003B_002A/@EntryIndexedValue">True</s:Boolean>
<s:Boolean
x:Key="/Default/Environment/Filtering/ExcludeCoverageFilters/=Versioning_003B_002A_003B_002A_003B_002A/@EntryIndexedValue">True</s:Boolean>
<s:Boolean
x:Key="/Default/Environment/SettingsMigration/IsMigratorApplied/=JetBrains_002EReSharper_002EPsi_002ECSharp_002ECodeStyle_002ECSharpKeepExistingMigration/@EntryIndexedValue">True</s:Boolean>
<s:Boolean
x:Key="/Default/Environment/SettingsMigration/IsMigratorApplied/=JetBrains_002EReSharper_002EPsi_002ECSharp_002ECodeStyle_002ECSharpPlaceEmbeddedOnSameLineMigration/@EntryIndexedValue">True</s:Boolean>
<s:Boolean
x:Key="/Default/Environment/SettingsMigration/IsMigratorApplied/=JetBrains_002EReSharper_002EPsi_002ECSharp_002ECodeStyle_002ECSharpUseContinuousIndentInsideBracesMigration/@EntryIndexedValue">True</s:Boolean>
<s:Boolean
x:Key="/Default/Environment/SettingsMigration/IsMigratorApplied/=JetBrains_002EReSharper_002EPsi_002ECSharp_002ECodeStyle_002ESettingsUpgrade_002EMigrateBlankLinesAroundFieldToBlankLinesAroundProperty/@EntryIndexedValue">True</s:Boolean></wpf:ResourceDictionary>

11
TTT/API/API.csproj Normal file
View File

@@ -0,0 +1,11 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>net8.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
<RootNamespace>TTT.API</RootNamespace>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="System.Text.Json" Version="8.0.5"/>
</ItemGroup>
</Project>

View File

@@ -0,0 +1,45 @@
namespace TTT.API.Command;
public enum CommandResult {
/// <summary>
/// The command ran successfully
/// </summary>
SUCCESS,
/// <summary>
/// The command ran into an error
/// </summary>
ERROR,
/// <summary>
/// The command was improperly formatted or otherwise
/// was not recognized by the command handler
/// </summary>
UNKNOWN_COMMAND,
/// <summary>
/// The command was passed invalid arguments, including
/// incorrect number, or an invalid target
/// </summary>
INVALID_ARGS,
/// <summary>
/// Similar to <see cref="INVALID_ARGS" />, but prompts
/// the Manager to print the usage of the command
/// </summary>
PRINT_USAGE,
/// <summary>
/// The executor of the command did not have
/// the required permissions. This may either
/// be due to a pre-check by the manager, or an
/// "execution" check by the command itself.
/// </summary>
NO_PERMISSION,
/// <summary>
/// This command can only be executed by a player
/// (i.e. not from the console)
/// </summary>
PLAYER_ONLY
}

View File

@@ -0,0 +1,13 @@
using TTT.API.Player;
namespace TTT.API.Command;
public interface ICommand : ITerrorModule {
string? Description => null;
string[] Usage => [];
string[] RequiredFlags => [];
string[] RequiredGroups => [];
string[] Aliases => [Id];
Task<CommandResult> Execute(IOnlinePlayer? executor, ICommandInfo info);
}

View File

@@ -0,0 +1,14 @@
using CounterStrikeSharp.API.Modules.Commands;
using TTT.API.Player;
namespace TTT.API.Command;
public interface ICommandInfo {
string[] Args { get; }
IOnlinePlayer? CallingPlayer { get; }
CommandCallingContext CallingContext { get; set; }
string CommandString => string.Join(' ', Args);
int ArgCount => Args.Length;
void ReplySync(string message);
ICommandInfo Skip(int count = 1);
}

View File

@@ -0,0 +1,32 @@
using TTT.API.Player;
namespace TTT.API.Command;
/// <summary>
/// An interface that allows for registering and processing commands.
/// </summary>
public interface ICommandManager {
ISet<ICommand> Commands { get; }
/// <summary>
/// Registers a command with the manager.
/// </summary>
/// <param name="command">True if the command was successfully registered.</param>
[Obsolete("Registration is done via the ServiceProvider now.")]
bool RegisterCommand(ICommand command);
/// <summary>
/// Unregisters a command from the manager.
/// </summary>
/// <param name="command">True if the command was successfully unregistered.</param>
bool UnregisterCommand(ICommand command);
bool CanExecute(IOnlinePlayer? executor, ICommand command);
/// <summary>
/// Attempts to process a command.
/// </summary>
/// <param name="info"></param>
/// <returns>True if the command finished processing successfully.</returns>
Task<CommandResult> ProcessCommand(ICommandInfo info);
}

View File

@@ -1,4 +1,4 @@
namespace TTT.Api.Events;
namespace TTT.API.Events;
public abstract class Event {
public abstract string Id { get; }

View File

@@ -0,0 +1,25 @@
namespace TTT.API.Events;
[AttributeUsage(AttributeTargets.Method)]
public class EventHandlerAttribute : Attribute {
public uint Priority { get; set; } = Events.Priority.DEFAULT;
public bool IgnoreCanceled { get; set; }
}
/// <summary>
/// Represents the priority levels for event handlers.
/// The lower the number, the higher the priority.
/// Higher priority handlers are executed before lower priority ones. Thus,
/// if you want a handler to have final say in an event's processing,
/// use a lower priority to be executed last.
/// </summary>
public static class Priority {
public const uint HIGHEST = 10;
public const uint HIGHER = 20;
public const uint HIGH = 40;
public const uint DEFAULT = 60;
public const uint LOW = 80;
public const uint LOWER = 100;
public const uint LOWEST = 200;
public const uint MONITOR = 1000;
}

View File

@@ -0,0 +1,5 @@
namespace TTT.API.Events;
public interface ICancelableEvent {
public bool IsCanceled { get; set; }
}

View File

@@ -1,8 +1,10 @@
namespace TTT.Api.Events;
namespace TTT.API.Events;
public interface IEventBus {
[Obsolete("Registration should be done via the ServiceProvider")]
void RegisterListener(IListener listener);
void UnregisterListener(IListener listener);
void Dispatch(Event ev);
Task Dispatch(Event ev);
}

View File

@@ -0,0 +1,5 @@
namespace TTT.API.Events;
public interface IListener : ITerrorModule {
void ITerrorModule.Start() { }
}

View File

@@ -0,0 +1,51 @@
using Microsoft.Extensions.DependencyInjection;
using TTT.API.Command;
using TTT.API.Events;
namespace TTT.API.Extensions;
/// <summary>
/// We use this to register all instances of <see cref="ITerrorModule" /> under
/// its interface, allowing us to get the list of all modules simply using ITerrorModule.
/// </summary>
public static class ServiceCollectionExtensions {
public static void AddModBehavior<TExtension>(
this IServiceCollection collection)
where TExtension : class, ITerrorModule {
if (typeof(TExtension).IsAssignableTo(typeof(IPluginModule)))
collection.AddTransient<IPluginModule>(provider
=> (provider.GetRequiredService<TExtension>() as IPluginModule)!);
if (typeof(TExtension).IsAssignableTo(typeof(IListener)))
collection.AddTransient<IListener>(provider
=> (provider.GetRequiredService<TExtension>() as IListener)!);
if (typeof(TExtension).IsAssignableTo(typeof(ICommand)))
collection.AddTransient<ICommand>(provider
=> (provider.GetRequiredService<TExtension>() as ICommand)!);
collection.AddScoped<TExtension>();
collection.AddTransient<ITerrorModule, TExtension>(provider
=> provider.GetRequiredService<TExtension>());
}
/// <summary>
/// Add a <see cref="ITerrorModule" /> to the global service collection
/// </summary>
/// <param name="collection"></param>
/// <typeparam name="TExtension"></typeparam>
/// <typeparam name="TInterface"></typeparam>
public static void AddModBehavior<TInterface, TExtension>(
this IServiceCollection collection)
where TExtension : class, ITerrorModule, TInterface
where TInterface : class {
// Add the root extension itself as a scoped service.
// This means every time Load is called in the main Jailbreak loader,
// the extension will be fetched and kept as a singleton for the duration
// until "Unload" is called.
collection.AddModBehavior<TExtension>();
collection.AddTransient<TInterface, TExtension>(p
=> p.GetRequiredService<TExtension>());
}
}

13
TTT/API/Game/EndReason.cs Normal file
View File

@@ -0,0 +1,13 @@
using TTT.API.Role;
namespace TTT.API.Game;
public record EndReason(string? Message, IRole? WinningRole = null) {
public EndReason(IRole role) : this(null, role) { }
public static EndReason TIMEOUT(IRole? defaultTeam) {
return new EndReason("Round ended due to timeout", defaultTeam);
}
public static EndReason ERROR(string err) { return new EndReason(err); }
}

26
TTT/API/Game/IAction.cs Normal file
View File

@@ -0,0 +1,26 @@
using TTT.API.Player;
using TTT.API.Role;
namespace TTT.API.Game;
public interface IAction {
IPlayer Player { get; }
IPlayer? Other { get; }
IRole? PlayerRole { get; }
IRole? OtherRole { get; }
string Id { get; }
string Verb { get; }
string Details { get; }
public string Format() {
var pRole = PlayerRole != null ?
$" [{PlayerRole.Name.First(char.IsAsciiLetter)}]" :
"";
var oRole = OtherRole != null ?
$" [{OtherRole.Name.First(char.IsAsciiLetter)}]" :
"";
return Other is not null ?
$"{Player}{pRole} {Verb} {Other}{oRole} {Details}" :
$"{Player}{pRole} {Verb} {Details}";
}
}

View File

@@ -0,0 +1,21 @@
using TTT.API.Player;
namespace TTT.API.Game;
public interface IActionLogger {
/// <summary>
/// Logs an action that has occurred in the game.
/// </summary>
/// <param name="action">The action to log.</param>
void LogAction(IAction action);
IEnumerable<(DateTime, IAction)> GetActions();
/// <summary>
/// Clears all logged actions.
/// </summary>
void ClearActions();
void PrintLogs();
void PrintLogs(IOnlinePlayer? player);
}

61
TTT/API/Game/IGame.cs Normal file
View File

@@ -0,0 +1,61 @@
using TTT.API.Player;
using TTT.API.Role;
namespace TTT.API.Game;
public interface IGame : IDisposable {
/// <summary>
/// The list of players in the game.
/// Spectators are not included in this list.
/// </summary>
ICollection<IPlayer> Players { get; }
public IList<IRole> Roles { get; }
IActionLogger Logger { get; }
DateTime? StartedAt { get; }
DateTime? FinishedAt { get; }
IRole? WinningRole { get; set; }
State State { get; set; }
IRoleAssigner RoleAssigner { get; init; }
/// <summary>
/// Attempts to start a game.
/// Depending on implementation, this may start a countdown or immediately start the game.
/// </summary>
/// <param name="countdown">TimeSpan for countdown, null means start immediately</param>
IObservable<long>? Start(TimeSpan? countdown = null);
void EndGame(EndReason? reason = null);
bool CheckEndConditions();
[Obsolete("This method is ambiguous, check the game state directly.")]
bool IsInProgress() { return State is State.COUNTDOWN or State.IN_PROGRESS; }
ISet<IOnlinePlayer> GetAlive() {
return Players.OfType<IOnlinePlayer>().Where(p => p.IsAlive).ToHashSet();
}
ISet<IOnlinePlayer> GetAlive(Type roleType, bool loose = true) {
if (!typeof(IRole).IsAssignableFrom(roleType))
throw new ArgumentException(
"roleType must be a type that implements IRole", nameof(roleType));
if (!loose)
return GetAlive()
.Where(p => RoleAssigner.GetRoles(p).Any(r => r.GetType() == roleType))
.ToHashSet();
return GetAlive()
.Where(p => RoleAssigner.GetRoles(p).Any(roleType.IsInstanceOfType))
.ToHashSet();
}
ISet<IOnlinePlayer> GetAlive(IRole role, bool loose = true) {
return GetAlive(role.GetType(), loose);
}
}

View File

@@ -0,0 +1,17 @@
namespace TTT.API.Game;
public interface IGameManager : IDisposable {
IGame? ActiveGame { get; protected set; }
void IDisposable.Dispose() {
ActiveGame?.Dispose();
ActiveGame = null;
}
IGame? CreateGame();
[Obsolete("This method is ambiguous, check the game state directly.")]
bool IsGameActive() {
return ActiveGame is not null && ActiveGame.IsInProgress();
}
}

23
TTT/API/Game/State.cs Normal file
View File

@@ -0,0 +1,23 @@
namespace TTT.API.Game;
public enum State {
/// <summary>
/// Waiting for players to join.
/// </summary>
WAITING,
/// <summary>
/// Waiting for the countdown to finish before starting the game.
/// </summary>
COUNTDOWN,
/// <summary>
/// Currently playing the game.
/// </summary>
IN_PROGRESS,
/// <summary>
/// Game has finished.
/// </summary>
FINISHED
}

9
TTT/API/IPluginModule.cs Normal file
View File

@@ -0,0 +1,9 @@
using CounterStrikeSharp.API.Core;
namespace TTT.API;
public interface IPluginModule : ITerrorModule {
void Start(BasePlugin? plugin) { Start(); }
void Start(BasePlugin? plugin, bool hotReload) { Start(plugin); }
}

8
TTT/API/ITerrorModule.cs Normal file
View File

@@ -0,0 +1,8 @@
namespace TTT.API;
public interface ITerrorModule : IDisposable {
string Id => GetType().Name;
string Version => GitVersionInformation.FullSemVer;
void Start();
}

18
TTT/API/IWeapon.cs Normal file
View File

@@ -0,0 +1,18 @@
namespace TTT.API;
public interface IWeapon {
/// <summary>
/// The internal ID of the weapon, should match the ID of the weapon in the underlying game.
/// </summary>
public string WeaponId { get; }
/// <summary>
/// The amount of ammo that is in reserve for this weapon.
/// </summary>
public int? ReserveAmmo { get; }
/// <summary>
/// The amount of ammo that is currently in the weapon's magazine or chamber.
/// </summary>
public int? CurrentAmmo { get; }
}

View File

@@ -0,0 +1,43 @@
using TTT.API.Player;
namespace TTT.API.Messages;
public interface IMessenger {
Task<bool> Message(IPlayer? player, string message, params object[] args);
void Debug(string msg, params object[] args);
void DebugInform(string msg, params object[] args) { Debug(msg, args); }
void DebugAnnounce(string msg, params object[] args) { Debug(msg, args); }
Task<bool> MessageAll(string message, params object[] args);
Task<bool> BackgroundMsgAll(string message, params object[] args);
Task<bool> ScreenMsgAll(string message, params object[] args);
/// <summary>
/// Attempt to send a message to a player without showing it on the screen.
/// This could mean sending to console, background file, or just
/// falling back to showing it on the screen.
/// </summary>
/// <param name="player"></param>
/// <param name="message"></param>
/// <param name="args"></param>
/// <returns></returns>
Task<bool> BackgroundMsg(IPlayer? player, string message,
params object[] args) {
return Message(player, message, args);
}
/// <summary>
/// Attempt to send a message to a player that will be shown on the screen using
/// an alternative method, such as a popup or a notification.
/// May just fall back to showing it on the screen if no alternative is available.
/// </summary>
/// <param name="player"></param>
/// <param name="message"></param>
/// <param name="args"></param>
/// <returns></returns>
Task<bool> ScreenMsg(IPlayer? player, string message, params object[] args) {
return Message(player, message, args);
}
}

View File

@@ -0,0 +1,16 @@
namespace TTT.API.Player;
/// <summary>
/// Assumes a maximum of 64 players.
/// Each bit in the bitmask represents whether a player is visible to the client.
/// Bit 0 is unused, bit 1 represents player 1, bit 2 represents player 2, and so on.
/// </summary>
public interface IIconManager {
ulong GetVisiblePlayers(int client);
void SetVisiblePlayers(int client, ulong playersBitmask);
void RevealToAll(int client);
void AddVisiblePlayer(int client, int player);
void RemoveVisiblePlayer(int client, int player);
void ClearAllVisibility();
}

View File

@@ -0,0 +1,29 @@
namespace TTT.API.Player;
public interface IInventoryManager {
/// <summary>
/// Gives a weapon to the player.
/// </summary>
/// <param name="player">The player to give the weapon to.</param>
/// <param name="weapon"></param>
Task GiveWeapon(IOnlinePlayer player, IWeapon weapon);
/// <summary>
/// Removes a weapon from the player.
/// </summary>
/// <param name="player">The player to remove the weapon from.</param>
/// <param name="weaponId">The ID of the weapon to remove.</param>
Task RemoveWeapon(IOnlinePlayer player, string weaponId);
Task RemoveWeapon(IOnlinePlayer player, IWeapon weapon) {
return RemoveWeapon(player, weapon.WeaponId);
}
Task RemoveWeaponInSlot(IOnlinePlayer player, int slot);
/// <summary>
/// Removes all weapons from the player.
/// </summary>
/// <param name="player">The player to remove all weapons from.</param>
Task RemoveAllWeapons(IOnlinePlayer player);
}

View File

@@ -0,0 +1,8 @@
namespace TTT.API.Player;
public interface IOnlinePlayer : IPlayer {
public int Health { get; set; }
public int MaxHealth { get; set; }
public int Armor { get; set; }
public bool IsAlive { get; set; }
}

View File

@@ -0,0 +1,6 @@
namespace TTT.API.Player;
public interface IPermissionManager {
bool HasFlags(IPlayer player, params string[] flags);
bool InGroups(IPlayer player, params string[] groups);
}

11
TTT/API/Player/IPlayer.cs Normal file
View File

@@ -0,0 +1,11 @@
namespace TTT.API.Player;
public interface IPlayer {
/// <summary>
/// The unique identifier for the player, should
/// be unique across all players at all times.
/// </summary>
string Id { get; }
string Name { get; }
}

View File

@@ -0,0 +1,6 @@
namespace TTT.API.Player;
public interface IPlayerConverter<T> : ITerrorModule {
public IPlayer GetPlayer(T player);
public T? GetPlayer(IPlayer player);
}

View File

@@ -0,0 +1,24 @@
namespace TTT.API.Player;
public interface IPlayerFinder {
public IOnlinePlayer AddPlayer(IOnlinePlayer player);
public void AddPlayers(params IOnlinePlayer[] players) {
foreach (var p in players) AddPlayer(p);
}
public IPlayer RemovePlayer(IPlayer player);
ISet<IOnlinePlayer> GetOnline();
IOnlinePlayer? GetPlayerById(string id) {
return string.IsNullOrEmpty(id) ?
null :
GetOnline().FirstOrDefault(p => p.Id == id);
}
IOnlinePlayer? GetPlayerByName(string name) {
var matches = GetOnline().Where(p => p.Name.Contains(name)).ToList();
return matches.Count == 1 ? matches[0] : null;
}
}

4
TTT/API/README.md Normal file
View File

@@ -0,0 +1,4 @@
# TTT - API
This project contains the public API for TTT.
No game logic, internal management, etc. is (or ever should be) included here.

24
TTT/API/Role/IRole.cs Normal file
View File

@@ -0,0 +1,24 @@
using System.Drawing;
using TTT.API.Player;
namespace TTT.API.Role;
/// <summary>
/// Represents a role that can be assigned to a player.
/// Does not necessarily imply they are in the game.
/// </summary>
public interface IRole : IEquatable<IRole> {
string Id { get; }
string Name { get; }
Color Color { get; }
bool IEquatable<IRole>.Equals(IRole? other) {
if (other is null) return false;
if (ReferenceEquals(this, other)) return true;
return Id == other.Id;
}
IOnlinePlayer? FindPlayerToAssign(ISet<IOnlinePlayer> players);
void OnAssign(IOnlinePlayer player) { }
}

View File

@@ -0,0 +1,29 @@
using TTT.API.Player;
using TTT.API.Storage;
namespace TTT.API.Role;
public interface IRoleAssigner : IKeyedStorage<IPlayer, ICollection<IRole>>,
IKeyWritable<IPlayer, ICollection<IRole>> {
/// <summary>
/// Will attempt to assign roles to all players in the set.
/// Note that game-specific behavior and logic will almost certainly
/// change how this behaves.
/// Role assigning will call <see cref="IRole.FindPlayerToAssign" /> on the
/// first role continuously until it returns null, then it will move on to
/// second role, and so on.
/// Thus, the order of roles **does matter**. If you want a role to be assigned
/// first, it should be the first in the list.
/// </summary>
/// <param name="players"></param>
/// <param name="roles"></param>
public void AssignRoles(ISet<IOnlinePlayer> players, IList<IRole> roles);
public void SetRole(IOnlinePlayer player, IRole role) {
Write(player, new List<IRole> { role }).GetAwaiter().GetResult();
}
public ICollection<IRole> GetRoles(IPlayer player) {
return Load(player).GetAwaiter().GetResult() ?? [];
}
}

View File

@@ -0,0 +1,10 @@
namespace TTT.API.Storage;
public interface IKeyWritable<TKey, TValue> where TKey : notnull {
/// <summary>
/// Writes new data to the storage, replacing any existing data for the given key.
/// </summary>
/// <param name="key">The key for which to write the new data.</param>
/// <param name="newData">The new data to write.</param>
Task Write(TKey key, TValue newData);
}

View File

@@ -0,0 +1,5 @@
namespace TTT.API.Storage;
public interface IKeyedStorage<TKey, TValue> where TKey : notnull {
Task<TValue?> Load(TKey key);
}

View File

@@ -0,0 +1,5 @@
namespace TTT.API.Storage;
public interface IStorage<T> where T : class {
Task<T?> Load();
}

View File

@@ -0,0 +1,5 @@
namespace TTT.API.Storage;
public interface IWriteable<in T> where T : class {
Task Write(T newData);
}

View File

@@ -0,0 +1,9 @@
using CounterStrikeSharp.API.Core;
namespace TTT.CS2.API;
public interface IAliveSpoofer {
ISet<CCSPlayerController> FakeAlivePlayers { get; }
void SpoofAlive(CCSPlayerController player);
void UnspoofAlive(CCSPlayerController player);
}

View File

@@ -0,0 +1,24 @@
using System.Diagnostics.CodeAnalysis;
using CounterStrikeSharp.API.Core;
using TTT.Game;
namespace TTT.CS2.API;
public interface IBodyTracker {
public IDictionary<IBody, CRagdollProp> Bodies { get; }
public IBody? ReverseLookup(CRagdollProp ragdoll) {
return Bodies.FirstOrDefault(x => x.Value == ragdoll).Key;
}
public bool TryReverseLookup(CRagdollProp ragdoll,
[MaybeNullWhen(false)] out IBody body) {
body = ReverseLookup(ragdoll);
return body != null;
}
public bool TryLookup(string id, out IBody? body) {
body = Bodies.Keys.FirstOrDefault(x => x.Id == id);
return body != null;
}
}

22
TTT/CS2/CS2.csproj Normal file
View File

@@ -0,0 +1,22 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>net8.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
<RootNamespace>TTT.CS2</RootNamespace>
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
</PropertyGroup>
<ItemGroup>
<ProjectReference Include="..\API\API.csproj"/>
<ProjectReference Include="..\Game\Game.csproj"/>
<ProjectReference Include="..\Karma\Karma.csproj"/>
<ProjectReference Include="..\ShopAPI\ShopAPI.csproj"/>
</ItemGroup>
<ItemGroup>
<Folder Include="RayTrace\"/>
</ItemGroup>
</Project>

27
TTT/CS2/CS2Body.cs Normal file
View File

@@ -0,0 +1,27 @@
using CounterStrikeSharp.API.Core;
using TTT.API;
using TTT.API.Player;
using TTT.Game;
namespace TTT.CS2;
public class CS2Body(CRagdollProp ragdoll, IPlayer player) : IBody {
public CRagdollProp Ragdoll { get; } = ragdoll;
public IPlayer OfPlayer { get; } = player;
public bool IsIdentified { get; set; }
public IWeapon? MurderWeapon { get; private set; }
public IPlayer? Killer { get; set; }
public string Id { get; } = ragdoll.Index.ToString();
public DateTime TimeOfDeath { get; } = DateTime.Now;
public CS2Body WithWeapon(IWeapon weapon) {
MurderWeapon = weapon;
return this;
}
public CS2Body WithKiller(IPlayer? killer) {
Killer = killer;
return this;
}
}

15
TTT/CS2/CS2Logger.cs Normal file
View File

@@ -0,0 +1,15 @@
using CounterStrikeSharp.API;
using TTT.API.Player;
using TTT.Game.Loggers;
namespace TTT.CS2;
public class CS2Logger(IServiceProvider provider) : SimpleLogger(provider) {
public override void PrintLogs() {
Server.NextWorldUpdate(() => base.PrintLogs());
}
public override void PrintLogs(IOnlinePlayer? player) {
Server.NextWorldUpdate(() => base.PrintLogs(player));
}
}

View File

@@ -0,0 +1,81 @@
using CounterStrikeSharp.API.Core;
using Microsoft.Extensions.DependencyInjection;
using ShopAPI.Configs;
using ShopAPI.Configs.Traitor;
using TTT.API.Command;
using TTT.API.Extensions;
using TTT.API.Game;
using TTT.API.Messages;
using TTT.API.Player;
using TTT.API.Storage;
using TTT.CS2.API;
using TTT.CS2.Command;
using TTT.CS2.Command.Test;
using TTT.CS2.Configs;
using TTT.CS2.Configs.ShopItems;
using TTT.CS2.Game;
using TTT.CS2.GameHandlers;
using TTT.CS2.GameHandlers.DamageCancelers;
using TTT.CS2.Hats;
using TTT.CS2.lang;
using TTT.CS2.Listeners;
using TTT.CS2.Player;
using TTT.Game;
using TTT.Locale;
namespace TTT.CS2;
public static class CS2ServiceCollection {
public static void AddCS2Services(this IServiceCollection collection) {
// TTT - CS2 Specific requirements
collection
.AddModBehavior<IPlayerConverter<CCSPlayerController>,
CCPlayerConverter>();
collection.AddModBehavior<ICommandManager, CS2CommandManager>();
collection.AddModBehavior<IAliveSpoofer, CS2AliveSpoofer>();
collection.AddModBehavior<IIconManager, RoleIconsHandler>();
// Configs
collection.AddModBehavior<IStorage<TTTConfig>, CS2GameConfig>();
collection.AddModBehavior<IStorage<ShopConfig>, CS2ShopConfig>();
collection
.AddModBehavior<IStorage<OneShotDeagleConfig>, CS2OneShotDeagleConfig>();
collection.AddModBehavior<IStorage<C4Config>, CS2C4Config>();
// TTT - CS2 Specific optionals
collection.AddScoped<ITextSpawner, TextSpawner>();
// GameHandlers
collection.AddModBehavior<BodySpawner>();
collection.AddModBehavior<CombatHandler>();
collection.AddModBehavior<DamageCanceler>();
collection.AddModBehavior<PlayerConnectionsHandler>();
collection.AddModBehavior<PropMover>();
collection.AddModBehavior<RoundEnd_GameEndHandler>();
collection.AddModBehavior<RoundStart_GameStartHandler>();
// Damage Cancelers
collection.AddModBehavior<OutOfRoundCanceler>();
collection.AddModBehavior<TaserListenCanceler>();
// Listeners
collection.AddModBehavior<BodyPickupListener>();
collection.AddModBehavior<IBodyTracker, BodyTracker>();
collection.AddModBehavior<LateSpawnListener>();
collection.AddModBehavior<PlayerStatsTracker>();
collection.AddModBehavior<RoundTimerListener>();
collection.AddModBehavior<ScreenColorApplier>();
// Commands
#if DEBUG
collection.AddModBehavior<TestCommand>();
#endif
collection.AddScoped<IGameManager, CS2GameManager>();
collection.AddScoped<IInventoryManager, CS2InventoryManager>();
collection.AddScoped<IMessenger, CS2Messenger>();
collection.AddScoped<IMsgLocalizer, StringLocalizer>();
collection.AddScoped<IPermissionManager, CS2PermManager>();
collection.AddScoped<IPlayerFinder, CS2PlayerFinder>();
}
}

View File

@@ -0,0 +1,87 @@
using CounterStrikeSharp.API.Modules.Commands;
using Microsoft.Extensions.DependencyInjection;
using TTT.API.Command;
using TTT.API.Messages;
using TTT.API.Player;
using TTT.CS2.Player;
namespace TTT.CS2.Command;
/// <summary>
/// A CS2-specific implementation of <see cref="ICommandInfo" />
/// This is responsible for keeping track of who
/// executed a command, what the parameters were when executing,
/// and the execution context.
/// </summary>
public class CS2CommandInfo : ICommandInfo {
private readonly IMessenger messenger;
private readonly IServiceProvider provider;
public CS2CommandInfo(IServiceProvider provider, IOnlinePlayer? executor,
int offset = 0, params string[] args) {
this.provider = provider;
messenger = provider.GetRequiredService<IMessenger>();
CallingPlayer = executor;
Args = args.Skip(offset).ToArray();
if (offset == 0 && Args.Length > 0) Args[0] = args[0].ToLower();
}
public CS2CommandInfo(IServiceProvider provider, CommandInfo info,
int offset = 0) {
this.provider = provider;
messenger = provider.GetRequiredService<IMessenger>();
if (info.CallingPlayer != null)
CallingPlayer = new CS2Player(info.CallingPlayer);
CallingContext = info.CallingContext;
Args = new string[info.ArgCount - offset];
for (var i = 0; i < info.ArgCount - offset; i++)
Args[i] = info.GetArg(i + offset);
if (offset == 0 && Args.Length > 0) Args[0] = Args[0].ToLower();
}
public CS2CommandInfo(IServiceProvider provider, ICommandInfo info,
int offset = 0) {
this.provider = provider;
messenger = provider.GetRequiredService<IMessenger>();
CallingPlayer = info.CallingPlayer;
CallingContext = info.CallingContext;
Args = info.Args.Skip(offset).ToArray();
if (offset == 0 && Args.Length > 0) Args[0] = Args[0].ToLower();
}
public string this[int index] => Args[index];
/// <summary>
/// The arguments the command consists of
/// </summary>
public string[] Args { get; }
/// <summary>
/// The player that executed the command
/// </summary>
public IOnlinePlayer? CallingPlayer { get; }
/// <summary>
/// The calling context of the command
/// </summary>
public CommandCallingContext CallingContext { get; set; }
public int ArgCount => Args.Length;
public string CommandString => string.Join(' ', Args);
public void ReplySync(string message) {
switch (CallingContext) {
case CommandCallingContext.Chat:
messenger.Message(CallingPlayer, message);
break;
case CommandCallingContext.Console:
messenger.BackgroundMsg(CallingPlayer, message);
break;
}
}
public ICommandInfo Skip(int count = 1) {
return new CS2CommandInfo(provider, this, count);
}
}

View File

@@ -0,0 +1,59 @@
using CounterStrikeSharp.API;
using CounterStrikeSharp.API.Core;
using CounterStrikeSharp.API.Modules.Commands;
using Microsoft.Extensions.DependencyInjection;
using TTT.API;
using TTT.API.Command;
using TTT.API.Player;
using TTT.Game.Commands;
using TTT.Game.lang;
namespace TTT.CS2.Command;
public class CS2CommandManager(IServiceProvider provider)
: CommandManager(provider), IPluginModule {
private const string COMMAND_PREFIX = "css_";
private readonly IPlayerConverter<CCSPlayerController> converter =
provider.GetRequiredService<IPlayerConverter<CCSPlayerController>>();
private BasePlugin? plugin;
public void Start(BasePlugin? basePlugin, bool hotReload) {
plugin = basePlugin;
base.Start();
}
public override bool RegisterCommand(ICommand command) {
var registration = command.Aliases.All(alias
=> cmdMap.TryAdd(COMMAND_PREFIX + alias, command));
if (!registration) return false;
foreach (var alias in command.Aliases)
plugin?.AddCommand(COMMAND_PREFIX + alias,
command.Description ?? string.Empty, processInternal);
return true;
}
private void
processInternal(CCSPlayerController? executor, CommandInfo info) {
var cs2Info = new CS2CommandInfo(Provider, info);
var wrapper = executor == null ?
null :
converter.GetPlayer(executor) as IOnlinePlayer;
Task.Run(async () => {
try {
Console.WriteLine($"Processing command: {cs2Info.CommandString}");
return await ProcessCommand(cs2Info);
} catch (Exception e) {
var msg = e.Message;
cs2Info.ReplySync(Localizer[GameMsgs.GENERIC_ERROR(msg)]);
await Server.NextWorldUpdateAsync(() => {
Console.WriteLine(
$"Encountered an error when processing command: \"{cs2Info.CommandString}\" by {wrapper?.Id}");
Console.WriteLine(e);
});
return CommandResult.ERROR;
}
});
}
}

View File

@@ -0,0 +1,29 @@
using CounterStrikeSharp.API;
using Microsoft.Extensions.DependencyInjection;
using TTT.API.Command;
using TTT.API.Player;
using TTT.CS2.API;
namespace TTT.CS2.Command.Test;
public class ForceAliveCommand(IServiceProvider provider) : ICommand {
private readonly IAliveSpoofer spoofer =
provider.GetRequiredService<IAliveSpoofer>();
public void Dispose() { }
public string Id => "forcealive";
public void Start() { }
public Task<CommandResult>
Execute(IOnlinePlayer? executor, ICommandInfo info) {
Server.NextWorldUpdate(() => {
foreach (var player in Utilities.GetPlayers()) spoofer.SpoofAlive(player);
});
info.ReplySync("Attempted to force alive.");
return Task.FromResult(CommandResult.SUCCESS);
}
}

Some files were not shown because too many files have changed in this diff Show More