107 Commits
Author SHA1 Message Date
js6pak 2407a99569 2.1.0 2022-12-22 12:55:08 +01:00
js6pak eded2830cc Update to 2022.12.8 2022-12-09 20:48:30 +01:00
js6pak 9ef4bd5dc6 Merge pull request #67 from miniduikboot/fix/cofindgame 2022-12-04 23:07:28 +01:00
miniduikbootandEdward Smale 678730ed0f Fix Game lists not working on legacy mm servers
This happens because InnerNetClient.CoConnect now sets the default
LastDisconnectReason to Unknown instead of ExitGame, which breaks the
public game list screen.

Co-Authored-By: Edward Smale <essmale2005@gmail.com>
2022-12-02 19:33:58 +01:00
js6pak da20e0990e Fix occasional NRE 2022-10-27 11:42:17 +02:00
js6pak 9246458919 Kick for not having reactor only when necessary 2022-10-27 11:41:41 +02:00
js6pak fa4cc03e33 Don't send chat messages if quick chat only is enabled 2022-10-27 11:31:45 +02:00
js6pak 67c89f99ed Update CI 2022-10-26 01:39:46 +02:00
js6pak 7155b45bef Push Reactor.Networking.Shared nightlies aswell 2022-10-25 23:59:55 +02:00
js6pak 6079ea8fd4 Remove epic workaround, it's no longer needed 2022-10-25 23:47:05 +02:00
AlexejheroYTBandjs6pak 0c8156aaf6 Add localization API (#64)
Co-authored-by: js6pak <kubastaron@hotmail.com>
2022-10-23 15:36:10 +02:00
js6pak f2da251ae5 Update to 2022.10.25 2022-10-23 15:14:36 +02:00
js6pak 128c4f436e Make KickWithReason effective only when sent from host 2022-10-23 15:08:31 +02:00
js6pak 8d67b08481 Update to 2022.10.18, build against steam only for now 2022-10-18 23:07:57 +02:00
js6pak 615f6b20e1 Add a pointer constructor back to StreamWrapper 2022-10-10 17:34:44 +02:00
js6pak da217c1627 Update CI 2022-10-09 21:55:53 +02:00
js6pak 2d148db013 Add xmldocs 2022-10-09 21:55:53 +02:00
js6pak ed05e563f0 Enable net analyzers and add stylecop 2022-10-09 16:09:02 +02:00
js6pak 81eea3eee2 Format whitespaces 2022-10-07 14:55:14 +02:00
AlexejheroYTBandjs6pak b7971d36a8 Refactor (#62)
Co-authored-by: js6pak <kubastaron@hotmail.com>
2022-10-06 18:47:40 +00:00
js6pak 5cc08363c7 Don't lock public toggle on local games 2022-10-04 21:57:23 +02:00
js6pak 6be7629187 Convert Reactor.Shared to a source-only nuget package 2022-10-04 21:53:19 +02:00
js6pak 04a32b486d Make Reactor.Benchmarks output needed dlls 2022-10-04 21:42:07 +02:00
js6pak 510711c184 Bump dependencies 2022-10-04 21:39:06 +02:00
js6pak 879c4181cc Patch only declared HandleRpc methods 2022-09-30 16:20:24 +02:00
js6pak af27afed80 Include mods loaded before reactor in modlist 2022-09-02 20:31:59 +02:00
js6pak d2bc7cce04 Fix handshake in local game 2022-09-02 20:31:44 +02:00
js6pak d01ea478f4 Protocol v3 2022-08-30 21:22:50 +02:00
js6pak f56aa32927 Update bepinex 2022-08-30 20:16:56 +02:00
js6pak 256f7617ad Add Reactor.Assets to the repo 2022-08-30 19:49:50 +02:00
js6pak 55c77a7651 Support instance method rpcs 2022-08-30 19:49:50 +02:00
js6pak f4631805f6 Add Ack callback support to custom rpcs 2022-08-30 19:49:50 +02:00
js6pak b751800b29 Global using logger 2022-08-30 19:49:50 +02:00
js6pak ffd58ddcd8 Update logger utility 2022-08-30 19:49:50 +02:00
js6pak 7fae71bdf2 Switch to coreclr bepinex 2022-08-30 19:49:50 +02:00
js6pak 5004ac8d5b Reformat code 2022-08-30 19:49:49 +02:00
js6pak c2047b033e Revert "Revert "Start working on http handshake support""
This reverts commit a6152f559c.
2022-08-23 20:59:19 +02:00
js6pak a6152f559c Revert "Start working on http handshake support"
This reverts commit 3579ecb89e.
2022-08-23 20:47:22 +02:00
js6pak 9893fc9e45 Add support for 2022.8.23 2022-08-23 20:36:20 +02:00
js6pak 16135fa897 Merge pull request #58 from miniduikboot/fix/ci-caching 2022-08-07 18:21:05 +00:00
miniduikboot 0eb6ac0cbe Fix CI Caching by cloning first
The cache action requires the checksum of the packages.lock.json files,
but can't find them because the repository wasn't cloned yet. So clone
the repository first
2022-08-07 19:50:32 +02:00
js6pak 3579ecb89e Start working on http handshake support 2022-07-30 01:00:58 +02:00
js6pak ff7a80addf Fix regioninfo watcher crashing when the file doesn't exist 2022-07-29 21:17:17 +02:00
js6pak ef6baeacce Fix epic splashskip fix 2022-07-29 21:00:35 +02:00
js6pak f24cbf182a 1.2.7 2022-06-24 04:58:30 +02:00
js6pak fdda5571b2 Bump dependencies 2022-06-24 04:58:10 +02:00
js6pak 89f06e01f1 Fix splash skip on epic 2022-06-24 04:50:17 +02:00
js6pak 0a03a9d90d Fix udp matchmaking 2022-06-03 21:49:56 +02:00
js6pak 22550a88ca 1.2.6 2022-05-31 00:40:18 +02:00
js6pak 2b98a211bd Merge pull request #55 from miniduikboot/fix/region-info-feedback-loop
Improve regionInfo.json writing logic
2022-05-30 21:43:05 +00:00
miniduikboot cb799e877e Improve regionInfo.json writing logic
Since a few version AU writes the regionInfo.json file after loading it.
This triggers the write observer, causing a positive feedback loop.
70155fe8a6 took the first stab at stopping
this positive feedback, but unfortunately it isn't adequate enough when
4+ clients are running at the same time, so this commit takes it a step
further by not writing the data if it didn't change, stopping the loop.
2022-05-30 23:38:15 +02:00
js6pak fcc8056aaa 1.2.5 2022-05-06 14:02:13 +02:00
js6pak c4a8c8abbe [skip ci] Create release from CI 2022-05-06 14:00:24 +02:00
js6pak 7203698222 Totally didn't forget to commit this 2022-04-01 10:08:10 +02:00
js6pak d3fa33aaf0 2022.3.29 2022-03-31 22:26:18 +02:00
js6pak bbcb1abb67 Merge pull request #53 from miniduikboot/fix/usedtls-desync 2022-03-09 22:54:14 +01:00
miniduikboot 9b1211f505 Add prefix patch to sync up useDtlsLayout argument
Workaround a much deeper, yet unknown issue
2022-03-03 22:01:19 +01:00
js6pak e58f8b5aef Update CustomServersPatch for 2022.2.8+ 2022-02-27 15:52:08 +01:00
js6pak bac31b1b51 Support 2022.2.23s and bump dependencies 2022-02-26 17:43:08 +01:00
amsyarasyiq d2e5d026e3 Patch random name generator (#46) 2022-02-18 21:54:03 +00:00
js6pak 081e6e2ba9 1.2.1 2022-02-18 22:40:48 +01:00
js6pak 70155fe8a6 Don't reload regionInfo.json when the game saves it 2022-02-18 22:38:35 +01:00
js6pak 89a8adadf7 2021.12.15 2021-12-21 15:53:08 +01:00
js6pak 837ee142b3 2021.12.14 2021-12-15 19:45:27 +01:00
js6pak 2453bff8df Merge branch '2021.11.9' 2021-12-14 23:17:43 +01:00
js6pak f501dc1897 RandomExtensions 2021-12-14 22:40:12 +01:00
js6pak f3b510ae2a Bump version to 1.2.0 2021-12-03 00:53:28 +01:00
js6pak bc9b8ea8a2 Merge remote-tracking branch 'origin/master' into 2021.11.9 2021-12-03 00:52:46 +01:00
Simon Kelly c96f12029e Allow sending method rpcs immediately (#45) 2021-11-24 15:28:51 +00:00
js6pak 8e8beaf30c Merge remote-tracking branch 'origin/master' into 2021.11.9
# Conflicts:
#	AmongUs.props
#	Reactor.Debugger/packages.lock.json
#	Reactor.Example/packages.lock.json
#	Reactor/packages.lock.json
2021-11-20 01:20:39 +01:00
js6pak d92447a490 Update packages 2021-11-19 23:24:32 +01:00
js6pak d9e5e7f1a9 Fix freeplay 2021-11-11 11:35:30 +01:00
js6pak 40ae06899c Update CI to .NET 6 2021-11-10 15:45:39 +01:00
js6pak 73e21fc406 2021.11.9 2021-11-10 15:43:17 +01:00
js6pak f63f1bc884 Fix method rpc registration 2021-11-06 12:14:14 +01:00
Simon Kelly 6613fb007f Use BepInEx Coroutines (#42) 2021-11-06 11:01:42 +00:00
js6pak 5f807e4122 Ensure it wont happen in future 2021-11-04 14:38:48 +01:00
js6pak 12d44b1482 Fix freeplay in some cases 2021-11-04 14:36:41 +01:00
js6pakandminiduikboot d5929c270a Add ServerInfoFixes
Co-authored-by: miniduikboot <mini@duikbo.at>
2021-11-02 21:18:26 +01:00
js6pak d39b31059f Delete PlayerColor 2021-11-02 20:24:23 +01:00
js6pak f8faf5117d Enable nullable 2021-11-02 20:07:28 +01:00
js6pak 111ef34298 Upgrade deps 2021-11-01 21:32:10 +01:00
js6pak 213bb27444 Add cache to CI 2021-11-01 00:51:13 +01:00
js6pak e0154f2fc5 Upgrade deps 2021-11-01 00:37:18 +01:00
js6pak 90536631f9 Dispose DefaultBundle stream 2021-10-31 02:58:51 +02:00
js6pak 7a84617b1b StreamWrapper 2021-10-31 02:12:26 +02:00
js6pak ad1635df9e Use even more new unhollower features 2021-10-30 21:26:42 +02:00
js6pak ade1cfc35f Fix imgui windows flickering 2021-10-30 13:43:36 +02:00
Simon Kellyandjs6pak dd3e49144d Support new unhollower features (#40)
Co-authored-by: js6pak <kubastaron@hotmail.com>
2021-10-29 21:12:51 +00:00
js6pak feb44ea6b6 Merge branch 'free-name-patch' into bepinex-upgrade 2021-10-24 01:37:36 +02:00
js6pak 534382a263 Merge branch 'method_rpc' into bepinex-upgrade
# Conflicts:
#	Reactor.Example/ExamplePlugin.cs
2021-10-24 01:34:12 +02:00
js6pak 88b3b39066 Initial BepInEx upgrade 2021-10-24 01:32:43 +02:00
js6pak 179cb84da2 PluginSide from AssemblyMetadataAttribute 2021-10-23 21:44:03 +02:00
amsyarasyiq 959c5b1fc8 Better math 2021-08-26 11:27:01 +08:00
amsyarasyiq 5d362b0885 Move objects 2021-08-26 08:59:42 +08:00
amsyarasyiq 089dada562 Readd FreeNamePatch 2021-08-26 08:57:21 +08:00
js6pak 1107480ea2 Add .editorconfig 2021-07-27 20:21:11 +02:00
js6pak 7d02cb9616 IL gen refactor and serialization changes 2021-07-27 16:18:11 +02:00
Zirno 41413eea20 Add ReaderWriter for custom types 2021-07-26 17:07:57 +02:00
Zirno c6d2ff686b Some Optimizations 2021-07-26 17:07:57 +02:00
Zirno 63fdde22c6 Add an Example 2021-07-26 17:07:57 +02:00
Zirno eb7fce3350 method Rpc 2021-07-26 17:07:57 +02:00
js6pak 0f0d322c8c BepInEx version check 2021-07-26 16:38:47 +02:00
js6pak 31e8bd4f6f Simplify CustomStringName patches 2021-07-21 00:22:35 +02:00
js6pak fbe03ebac5 Fix coroutine exception handling 2021-07-07 20:41:30 +02:00
js6pak c009f5a7a2 2021.6.30 2021-07-07 19:17:17 +02:00
js6pak 51b5ec8f3a Update Reactor.MSBuild 2021-06-30 21:28:45 +02:00
170 changed files with 11072 additions and 2522 deletions

No files matched your search

+1 -1
View File
@@ -3,7 +3,7 @@
"isRoot": true,
"tools": {
"cake.tool": {
"version": "1.1.0",
"version": "2.2.0",
"commands": [
"dotnet-cake"
]
+227
View File
@@ -1,3 +1,230 @@
# top-most EditorConfig file
root = true
[*]
indent_style = space
charset = utf-8
end_of_line = lf
insert_final_newline = true
# Code files
[*.{cs, csx, vb, vbx}]
indent_size = 4
# XML project files
[*.{csproj, vbproj, vcxproj, vcxproj.filters, proj, projitems, shproj}]
indent_size = 4
# XML config files
[*.{props, targets, ruleset, config, nuspec, resx, vsixmanifest, vsct}]
indent_size = 4
# Dotnet code style settings:
[*.{cs, vb}]
# IDE0055: Fix formatting
dotnet_diagnostic.IDE0055.severity = warning
# Sort using and Import directives with System.* appearing first
dotnet_sort_system_directives_first = true
dotnet_separate_import_directive_groups = false
# Avoid "this." and "Me." if not necessary
dotnet_style_qualification_for_field = false:refactoring
dotnet_style_qualification_for_property = false:refactoring
dotnet_style_qualification_for_method = false:refactoring
dotnet_style_qualification_for_event = false:refactoring
# Use language keywords instead of framework type names for type references
dotnet_style_predefined_type_for_locals_parameters_members = true:suggestion
dotnet_style_predefined_type_for_member_access = true:suggestion
# Suggest more modern language features when available
dotnet_style_object_initializer = true:suggestion
dotnet_style_collection_initializer = true:suggestion
dotnet_style_coalesce_expression = true:suggestion
dotnet_style_null_propagation = true:suggestion
dotnet_style_explicit_tuple_names = true:suggestion
# Non-private static fields are PascalCase
dotnet_naming_rule.non_private_static_fields_should_be_pascal_case.severity = suggestion
dotnet_naming_rule.non_private_static_fields_should_be_pascal_case.symbols = non_private_static_fields
dotnet_naming_rule.non_private_static_fields_should_be_pascal_case.style = non_private_static_field_style
dotnet_naming_symbols.non_private_static_fields.applicable_kinds = field
dotnet_naming_symbols.non_private_static_fields.applicable_accessibilities = public, protected, internal, protected_internal, private_protected
dotnet_naming_symbols.non_private_static_fields.required_modifiers = static
dotnet_naming_style.non_private_static_field_style.capitalization = pascal_case
# Non-private readonly fields are PascalCase
dotnet_naming_rule.non_private_readonly_fields_should_be_pascal_case.severity = suggestion
dotnet_naming_rule.non_private_readonly_fields_should_be_pascal_case.symbols = non_private_readonly_fields
dotnet_naming_rule.non_private_readonly_fields_should_be_pascal_case.style = non_private_readonly_field_style
dotnet_naming_symbols.non_private_readonly_fields.applicable_kinds = field
dotnet_naming_symbols.non_private_readonly_fields.applicable_accessibilities = public, protected, internal, protected_internal, private_protected
dotnet_naming_symbols.non_private_readonly_fields.required_modifiers = readonly
dotnet_naming_style.non_private_readonly_field_style.capitalization = pascal_case
# Constants are PascalCase
dotnet_naming_rule.constants_should_be_pascal_case.severity = suggestion
dotnet_naming_rule.constants_should_be_pascal_case.symbols = constants
dotnet_naming_rule.constants_should_be_pascal_case.style = constant_style
dotnet_naming_symbols.constants.applicable_kinds = field, local
dotnet_naming_symbols.constants.required_modifiers = const
dotnet_naming_style.constant_style.capitalization = pascal_case
# Instance fields are camelCase and start with _
dotnet_naming_rule.instance_fields_should_be_camel_case.severity = suggestion
dotnet_naming_rule.instance_fields_should_be_camel_case.symbols = instance_fields
dotnet_naming_rule.instance_fields_should_be_camel_case.style = instance_field_style
dotnet_naming_symbols.instance_fields.applicable_kinds = field
dotnet_naming_style.instance_field_style.capitalization = camel_case
dotnet_naming_style.instance_field_style.required_prefix = _
# Locals and parameters are camelCase
dotnet_naming_rule.locals_should_be_camel_case.severity = suggestion
dotnet_naming_rule.locals_should_be_camel_case.symbols = locals_and_parameters
dotnet_naming_rule.locals_should_be_camel_case.style = camel_case_style
dotnet_naming_symbols.locals_and_parameters.applicable_kinds = parameter, local
dotnet_naming_style.camel_case_style.capitalization = camel_case
# Local functions are PascalCase
dotnet_naming_rule.local_functions_should_be_pascal_case.severity = suggestion
dotnet_naming_rule.local_functions_should_be_pascal_case.symbols = local_functions
dotnet_naming_rule.local_functions_should_be_pascal_case.style = local_function_style
dotnet_naming_symbols.local_functions.applicable_kinds = local_function
dotnet_naming_style.local_function_style.capitalization = pascal_case
# By default, name items with PascalCase
dotnet_naming_rule.members_should_be_pascal_case.severity = suggestion
dotnet_naming_rule.members_should_be_pascal_case.symbols = all_members
dotnet_naming_rule.members_should_be_pascal_case.style = pascal_case_style
dotnet_naming_symbols.all_members.applicable_kinds = *
dotnet_naming_style.pascal_case_style.capitalization = pascal_case
# Async methods should have "Async" suffix
dotnet_naming_rule.async_methods_end_in_async.symbols = any_async_methods
dotnet_naming_rule.async_methods_end_in_async.style = end_in_async
dotnet_naming_rule.async_methods_end_in_async.severity = warning
dotnet_naming_symbols.any_async_methods.applicable_kinds = method
dotnet_naming_symbols.any_async_methods.applicable_accessibilities = *
dotnet_naming_symbols.any_async_methods.required_modifiers = async
dotnet_naming_style.end_in_async.required_prefix =
dotnet_naming_style.end_in_async.required_suffix = Async
dotnet_naming_style.end_in_async.capitalization = pascal_case
dotnet_naming_style.end_in_async.word_separator =
# error RS2008: Enable analyzer release tracking for the analyzer project containing rule '{0}'
dotnet_diagnostic.RS2008.severity = none
# IDE0005: Remove unnecessary import
dotnet_diagnostic.IDE0005.severity = warning
# IDE0007: Use `var` instead of explicit type
dotnet_diagnostic.IDE0007.severity = warning
# IDE0035: Remove unreachable code
dotnet_diagnostic.IDE0035.severity = warning
# IDE0036: Order modifiers
dotnet_diagnostic.IDE0036.severity = warning
# IDE0043: Format string contains invalid placeholder
dotnet_diagnostic.IDE0043.severity = warning
# IDE0044: Make field readonly
dotnet_diagnostic.IDE0044.severity = warning
dotnet_diagnostic.CA1000.severity = none
dotnet_diagnostic.CA1016.severity = none
dotnet_diagnostic.CA1711.severity = none
dotnet_diagnostic.CA1716.severity = none
dotnet_diagnostic.CA1720.severity = none
[Reactor.Benchmarks/*.cs]
dotnet_diagnostic.CA1707.severity = none
dotnet_diagnostic.CA1822.severity = none
# CSharp code style settings:
[*.cs]
# Newline settings
csharp_new_line_before_open_brace = all
csharp_new_line_before_else = true
csharp_new_line_before_catch = true
csharp_new_line_before_finally = true
# csharp_new_line_before_members_in_object_initializers = true TODO seems like Rider/ReSharper has the value inverted, uncomment when its fixed
csharp_new_line_before_members_in_anonymous_types = true
csharp_new_line_between_query_expression_clauses = true
# Indentation preferences
csharp_indent_block_contents = true
csharp_indent_braces = false
csharp_indent_case_contents = true
csharp_indent_case_contents_when_block = false
csharp_indent_switch_labels = true
csharp_indent_labels = flush_left
# Prefer "var" everywhere
csharp_style_var_for_built_in_types = true:suggestion
csharp_style_var_when_type_is_apparent = true:suggestion
csharp_style_var_elsewhere = true:suggestion
# Prefer method-like constructs to have a block body
csharp_style_expression_bodied_methods = false:none
csharp_style_expression_bodied_constructors = false:none
csharp_style_expression_bodied_operators = false:none
# Prefer property-like constructs to have an expression-body
csharp_style_expression_bodied_properties = true:none
csharp_style_expression_bodied_indexers = true:none
csharp_style_expression_bodied_accessors = true:none
# Suggest more modern language features when available
csharp_style_pattern_matching_over_is_with_cast_check = true:suggestion
csharp_style_pattern_matching_over_as_with_null_check = true:suggestion
csharp_style_inlined_variable_declaration = true:suggestion
csharp_style_throw_expression = true:suggestion
csharp_style_conditional_delegate_call = true:suggestion
# Space preferences
csharp_space_after_cast = true
csharp_space_after_colon_in_inheritance_clause = true
csharp_space_after_comma = true
csharp_space_after_dot = false
csharp_space_after_keywords_in_control_flow_statements = true
csharp_space_after_semicolon_in_for_statement = true
csharp_space_around_binary_operators = before_and_after
csharp_space_around_declaration_statements = do_not_ignore
csharp_space_before_colon_in_inheritance_clause = true
csharp_space_before_comma = false
csharp_space_before_dot = false
csharp_space_before_open_square_brackets = false
csharp_space_before_semicolon_in_for_statement = false
csharp_space_between_empty_square_brackets = false
csharp_space_between_method_call_empty_parameter_list_parentheses = false
csharp_space_between_method_call_name_and_opening_parenthesis = false
csharp_space_between_method_call_parameter_list_parentheses = false
csharp_space_between_method_declaration_empty_parameter_list_parentheses = false
csharp_space_between_method_declaration_name_and_open_parenthesis = false
csharp_space_between_method_declaration_parameter_list_parentheses = false
csharp_space_between_parentheses = false
csharp_space_between_square_brackets = false
# Blocks are allowed
csharp_prefer_braces = true:silent
csharp_preserve_single_line_blocks = true
csharp_preserve_single_line_statements = true
+35 -10
View File
@@ -1,37 +1,62 @@
name: CI
on: [ "push", "pull_request" ]
on: ["push", "pull_request"]
jobs:
build:
runs-on: ubuntu-20.04
steps:
- uses: actions/checkout@v2
- uses: actions/checkout@v3
with:
submodules: true
- name: Setup .NET
uses: actions/setup-dotnet@v1
- uses: actions/cache@v3
with:
dotnet-version: 5.x
path: |
~/.nuget/packages
~/.cache/bepinex
key: ${{ runner.os }}-nuget-${{ hashFiles('**/packages.lock.json') }}
restore-keys: |
${{ runner.os }}-nuget-
- name: Setup .NET
uses: actions/setup-dotnet@v2
with:
dotnet-version: 6.x
- name: Run the Cake script
uses: cake-build/cake-action@v1
with:
verbosity: Diagnostic
- uses: actions/upload-artifact@v2
- uses: actions/upload-artifact@v3
with:
name: Reactor.dll
path: Reactor/bin/Release/netstandard2.1/Reactor.dll
path: Reactor/bin/Release/net6.0/Reactor.dll
- uses: actions/upload-artifact@v2
- uses: actions/upload-artifact@v3
with:
name: Reactor.nupkg
path: Reactor/bin/Release/Reactor.*.nupkg
- uses: actions/upload-artifact@v2
- uses: actions/upload-artifact@v3
with:
name: Reactor.Networking.Shared.nupkg
path: Reactor.Networking.Shared/bin/Release/*.nupkg
- uses: actions/upload-artifact@v3
with:
name: Reactor.Debugger.dll
path: Reactor.Debugger/bin/Release/netstandard2.1/Reactor.Debugger.dll
path: Reactor.Debugger/bin/Release/net6.0/Reactor.Debugger.dll
- uses: softprops/action-gh-release@v1
if: github.ref_type == 'tag'
with:
draft: true
files: Reactor/bin/Release/net6.0/Reactor.dll
- name: Push nightly NuGet package
if: github.repository == 'NuclearPowered/Reactor' && github.ref == 'refs/heads/master'
run: |
dotnet nuget push {Reactor/bin/Release/Reactor.*.nupkg,Reactor.Networking.Shared/bin/Release/*.nupkg} --source https://nuget.reactor.gg/v3/index.json --api-key ${{ secrets.REACTOR_NUGET_KEY }}
+44
View File
@@ -0,0 +1,44 @@
name: Unity
on:
push:
paths: [ "Reactor.Assets/**", "Reactor/Assets/*.bundle", ".github/workflows/unity.yml" ]
jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- uses: actions/cache@v3
with:
path: |
~/Unity/Hub/Editor
~/.config/unityhub
key: unity-2020.3.22f1
- name: Setup Unity
uses: js6pak/setup-unity@master
with:
project-path: ./Reactor.Assets
unity-modules: windows-mono android
- name: Activate Unity
uses: js6pak/activate-unity@master
with:
unity-username: ${{ secrets.UNITY_USERNAME }}
unity-password: ${{ secrets.UNITY_PASSWORD }}
unity-authenticator-key: ${{ secrets.UNITY_AUTHENTICATOR_KEY }}
- name: Build
working-directory: ./Reactor.Assets
run: bash ./build.sh
- uses: actions/upload-artifact@v3
with:
name: bundles
path: ./Reactor/Assets/*.bundle
- name: Verify
run: if [[ $(git status --porcelain) ]]; then git status; git diff; exit 1; fi
+1
View File
@@ -6,3 +6,4 @@ riderModule.iml
.idea
/tools
.vscode
*.DotSettings.user
+6 -16
View File
@@ -1,23 +1,13 @@
<Project>
<PropertyGroup>
<GamePlatform Condition="'$(GamePlatform)' == ''">Steam</GamePlatform>
<GameVersion Condition="'$(GamePlatform)' == 'Steam'">2021.6.15s</GameVersion>
<GameVersion Condition="'$(GamePlatform)' == 'Itch'">2021.6.15i</GameVersion>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)' == 'Debug'">
<GameProvider>$(GamePlatform)</GameProvider>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)' == 'Release'">
<GameProvider>Github</GameProvider>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Reactor.MSBuild" Version="0.1.4" PrivateAssets="all" />
<PackageReference Include="BepInEx.Unity.IL2CPP" Version="6.0.0-be.663" Private="false" ExcludeAssets="runtime;native" />
<PackageReference Include="AmongUs.GameLibs.Steam" Version="2022.12.8" PrivateAssets="all" />
<PackageReference Include="BepInEx.AutoPlugin" Version="1.1.0" PrivateAssets="all" />
<PackageReference Include="BepInEx.IL2CPP.MSBuild" Version="2.0.1" PrivateAssets="all" ExcludeAssets="runtime" />
</ItemGroup>
<Target Name="Copy" AfterTargets="Build" Condition="'$(AmongUs)' != ''">
<Copy SourceFiles="$(OutputPath)$(AssemblyName).dll" DestinationFolder="$(AmongUs)/BepInEx/plugins/" Condition="'$(Configuration)' == 'Debug'" />
<Copy SourceFiles="$(TargetPath)" DestinationFolder="$(AmongUs)/BepInEx/plugins/" UseSymboliclinksIfPossible="true" />
</Target>
</Project>
+39
View File
@@ -0,0 +1,39 @@
<Project>
<PropertyGroup>
<TargetFramework>net6.0</TargetFramework>
<LangVersion>latest</LangVersion>
<DebugType>embedded</DebugType>
<Nullable>enable</Nullable>
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
<RestorePackagesWithLockFile>true</RestorePackagesWithLockFile>
<VersionPrefix>2.1.0</VersionPrefix>
<VersionSuffix>dev</VersionSuffix>
<Authors>NuclearPowered</Authors>
<PackageIcon>icon.png</PackageIcon>
<RepositoryType>git</RepositoryType>
<RepositoryUrl>https://github.com/NuclearPowered/Reactor</RepositoryUrl>
<PackageLicenseExpression>LGPL-3.0-or-later</PackageLicenseExpression>
</PropertyGroup>
<ItemGroup>
<None Include="$(MSBuildThisFileDirectory)\assets\icon.png" Pack="true" PackagePath="" Visible="false" />
</ItemGroup>
<PropertyGroup>
<EnableNETAnalyzers>true</EnableNETAnalyzers>
<AnalysisLevel>latest</AnalysisLevel>
<AnalysisMode>recommended</AnalysisMode>
<EnforceCodeStyleInBuild>true</EnforceCodeStyleInBuild>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="StyleCop.Analyzers" Version="1.2.0-beta.435" PrivateAssets="all" />
<AdditionalFiles Include="$(MSBuildThisFileDirectory)\stylecop.json" Link="stylecop.json" Visible="false" />
</ItemGroup>
<PropertyGroup>
<CodeAnalysisRuleSet>$(MSBuildThisFileDirectory)\stylecop.ruleset</CodeAnalysisRuleSet>
</PropertyGroup>
</Project>
+9
View File
@@ -0,0 +1,9 @@
*
!.gitignore
!Assets/
!Assets/**
!Packages/
!Packages/**
!ProjectSettings/
!ProjectSettings/ProjectVersion.txt
!build.sh
+8
View File
@@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: ae7df23e94a4b0c83a418e20686437d1
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:
@@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 5425e70810911f650b05cf41f536c339
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:
@@ -0,0 +1,116 @@
// Unity built-in shader source. Copyright (c) 2016 Unity Technologies. MIT license (see license.txt)
Shader "UI/Default"
{
Properties
{
[PerRendererData] _MainTex ("Sprite Texture", 2D) = "white" {}
_Color ("Tint", Color) = (1,1,1,1)
_StencilComp ("Stencil Comparison", Float) = 8
_Stencil ("Stencil ID", Float) = 0
_StencilOp ("Stencil Operation", Float) = 0
_StencilWriteMask ("Stencil Write Mask", Float) = 255
_StencilReadMask ("Stencil Read Mask", Float) = 255
_ColorMask ("Color Mask", Float) = 15
[Toggle(UNITY_UI_ALPHACLIP)] _UseUIAlphaClip ("Use Alpha Clip", Float) = 0
}
SubShader
{
Tags
{
"Queue"="Transparent"
"IgnoreProjector"="True"
"RenderType"="Transparent"
"PreviewType"="Plane"
"CanUseSpriteAtlas"="True"
}
Stencil
{
Ref [_Stencil]
Comp [_StencilComp]
Pass [_StencilOp]
ReadMask [_StencilReadMask]
WriteMask [_StencilWriteMask]
}
Cull Off
Lighting Off
ZWrite Off
ZTest [unity_GUIZTestMode]
Blend SrcAlpha OneMinusSrcAlpha
ColorMask [_ColorMask]
Pass
{
Name "Default"
CGPROGRAM
#pragma vertex vert
#pragma fragment frag
#pragma target 2.0
#include "UnityCG.cginc"
#include "UnityUI.cginc"
#pragma multi_compile_local _ UNITY_UI_CLIP_RECT
#pragma multi_compile_local _ UNITY_UI_ALPHACLIP
struct appdata_t
{
float4 vertex : POSITION;
float4 color : COLOR;
float2 texcoord : TEXCOORD0;
UNITY_VERTEX_INPUT_INSTANCE_ID
};
struct v2f
{
float4 vertex : SV_POSITION;
fixed4 color : COLOR;
float2 texcoord : TEXCOORD0;
float4 worldPosition : TEXCOORD1;
UNITY_VERTEX_OUTPUT_STEREO
};
sampler2D _MainTex;
fixed4 _Color;
fixed4 _TextureSampleAdd;
float4 _ClipRect;
float4 _MainTex_ST;
v2f vert(appdata_t v)
{
v2f OUT;
UNITY_SETUP_INSTANCE_ID(v);
UNITY_INITIALIZE_VERTEX_OUTPUT_STEREO(OUT);
OUT.worldPosition = v.vertex;
OUT.vertex = UnityObjectToClipPos(OUT.worldPosition);
OUT.texcoord = TRANSFORM_TEX(v.texcoord, _MainTex);
OUT.color = v.color * _Color;
return OUT;
}
fixed4 frag(v2f IN) : SV_Target
{
half4 color = (tex2D(_MainTex, IN.texcoord) + _TextureSampleAdd) * IN.color;
#ifdef UNITY_UI_CLIP_RECT
color.a *= UnityGet2DClipping(IN.worldPosition.xy, _ClipRect);
#endif
#ifdef UNITY_UI_ALPHACLIP
clip (color.a - 0.001);
#endif
return color;
}
ENDCG
}
}
}
@@ -0,0 +1,9 @@
fileFormatVersion: 2
guid: ba8fc08df3e3f060089297eca021e4d4
ShaderImporter:
externalObjects: {}
defaultTextures: []
nonModifiableTextures: []
userData:
assetBundleName:
assetBundleVariant:
@@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: e90cbb1a99b248a86995ee7f3c98c535
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:
@@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 68078bcc7def68b6088cdcf1eb1b4e9b
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:
Binary file not shown.

After

Width:  |  Height:  |  Size: 682 B

@@ -0,0 +1,120 @@
fileFormatVersion: 2
guid: 65b1cd3c5eee8851e847e241c19b9255
TextureImporter:
internalIDToNameTable: []
externalObjects: {}
serializedVersion: 11
mipmaps:
mipMapMode: 0
enableMipMap: 0
sRGBTexture: 1
linearTexture: 0
fadeOut: 0
borderMipMap: 0
mipMapsPreserveCoverage: 0
alphaTestReferenceValue: 0.5
mipMapFadeDistanceStart: 1
mipMapFadeDistanceEnd: 3
bumpmap:
convertToNormalMap: 0
externalNormalMap: 0
heightScale: 0.25
normalMapFilter: 0
isReadable: 0
streamingMipmaps: 0
streamingMipmapsPriority: 0
vTOnly: 0
grayScaleToAlpha: 0
generateCubemap: 6
cubemapConvolution: 0
seamlessCubemap: 0
textureFormat: 1
maxTextureSize: 2048
textureSettings:
serializedVersion: 2
filterMode: 1
aniso: 1
mipBias: 0
wrapU: 1
wrapV: 1
wrapW: 1
nPOTScale: 0
lightmap: 0
compressionQuality: 50
spriteMode: 1
spriteExtrude: 1
spriteMeshType: 0
alignment: 0
spritePivot: {x: 0.5, y: 0.5}
spritePixelsToUnits: 200
spriteBorder: {x: 10, y: 10, z: 10, w: 10}
spriteGenerateFallbackPhysicsShape: 1
alphaUsage: 1
alphaIsTransparency: 1
spriteTessellationDetail: -1
textureType: 8
textureShape: 1
singleChannelComponent: 0
flipbookRows: 1
flipbookColumns: 1
maxTextureSizeSet: 0
compressionQualitySet: 0
textureFormatSet: 0
ignorePngGamma: 0
applyGammaDecoding: 0
platformSettings:
- serializedVersion: 3
buildTarget: DefaultTexturePlatform
maxTextureSize: 2048
resizeAlgorithm: 0
textureFormat: -1
textureCompression: 1
compressionQuality: 100
crunchedCompression: 1
allowsAlphaSplitting: 0
overridden: 0
androidETC2FallbackOverride: 0
forceMaximumCompressionQuality_BC6H_BC7: 0
- serializedVersion: 3
buildTarget: Standalone
maxTextureSize: 2048
resizeAlgorithm: 0
textureFormat: -1
textureCompression: 1
compressionQuality: 100
crunchedCompression: 1
allowsAlphaSplitting: 0
overridden: 0
androidETC2FallbackOverride: 0
forceMaximumCompressionQuality_BC6H_BC7: 0
- serializedVersion: 3
buildTarget: Android
maxTextureSize: 2048
resizeAlgorithm: 0
textureFormat: -1
textureCompression: 1
compressionQuality: 100
crunchedCompression: 1
allowsAlphaSplitting: 0
overridden: 0
androidETC2FallbackOverride: 0
forceMaximumCompressionQuality_BC6H_BC7: 0
spriteSheet:
serializedVersion: 2
sprites: []
outline: []
physicsShape: []
bones: []
spriteID: 5e97eb03825dee720800000000000000
internalID: 0
vertices: []
indices:
edges: []
weights: []
secondaryTextures: []
spritePackingTag:
pSDRemoveMatte: 0
pSDShowRemoveMatteOption: 0
userData:
assetBundleName:
assetBundleVariant:
Binary file not shown.

After

Width:  |  Height:  |  Size: 636 B

@@ -0,0 +1,120 @@
fileFormatVersion: 2
guid: d08be60d3e2df0be09c5425e53870ba2
TextureImporter:
internalIDToNameTable: []
externalObjects: {}
serializedVersion: 11
mipmaps:
mipMapMode: 0
enableMipMap: 0
sRGBTexture: 1
linearTexture: 0
fadeOut: 0
borderMipMap: 0
mipMapsPreserveCoverage: 0
alphaTestReferenceValue: 0.5
mipMapFadeDistanceStart: 1
mipMapFadeDistanceEnd: 3
bumpmap:
convertToNormalMap: 0
externalNormalMap: 0
heightScale: 0.25
normalMapFilter: 0
isReadable: 0
streamingMipmaps: 0
streamingMipmapsPriority: 0
vTOnly: 0
grayScaleToAlpha: 0
generateCubemap: 6
cubemapConvolution: 0
seamlessCubemap: 0
textureFormat: 1
maxTextureSize: 2048
textureSettings:
serializedVersion: 2
filterMode: 1
aniso: 1
mipBias: 0
wrapU: 1
wrapV: 1
wrapW: 1
nPOTScale: 0
lightmap: 0
compressionQuality: 50
spriteMode: 1
spriteExtrude: 1
spriteMeshType: 1
alignment: 0
spritePivot: {x: 0.5, y: 0.5}
spritePixelsToUnits: 100
spriteBorder: {x: 0, y: 0, z: 0, w: 0}
spriteGenerateFallbackPhysicsShape: 1
alphaUsage: 1
alphaIsTransparency: 1
spriteTessellationDetail: -1
textureType: 8
textureShape: 1
singleChannelComponent: 0
flipbookRows: 1
flipbookColumns: 1
maxTextureSizeSet: 0
compressionQualitySet: 0
textureFormatSet: 0
ignorePngGamma: 0
applyGammaDecoding: 0
platformSettings:
- serializedVersion: 3
buildTarget: DefaultTexturePlatform
maxTextureSize: 2048
resizeAlgorithm: 0
textureFormat: -1
textureCompression: 1
compressionQuality: 100
crunchedCompression: 1
allowsAlphaSplitting: 0
overridden: 0
androidETC2FallbackOverride: 0
forceMaximumCompressionQuality_BC6H_BC7: 0
- serializedVersion: 3
buildTarget: Standalone
maxTextureSize: 2048
resizeAlgorithm: 0
textureFormat: -1
textureCompression: 1
compressionQuality: 100
crunchedCompression: 1
allowsAlphaSplitting: 0
overridden: 0
androidETC2FallbackOverride: 0
forceMaximumCompressionQuality_BC6H_BC7: 0
- serializedVersion: 3
buildTarget: Android
maxTextureSize: 2048
resizeAlgorithm: 0
textureFormat: -1
textureCompression: 1
compressionQuality: 100
crunchedCompression: 1
allowsAlphaSplitting: 0
overridden: 0
androidETC2FallbackOverride: 0
forceMaximumCompressionQuality_BC6H_BC7: 0
spriteSheet:
serializedVersion: 2
sprites: []
outline: []
physicsShape: []
bones: []
spriteID: 5e97eb03825dee720800000000000000
internalID: 0
vertices: []
indices:
edges: []
weights: []
secondaryTextures: []
spritePackingTag:
pSDRemoveMatte: 0
pSDShowRemoveMatteOption: 0
userData:
assetBundleName:
assetBundleVariant:
Binary file not shown.

After

Width:  |  Height:  |  Size: 347 B

@@ -0,0 +1,120 @@
fileFormatVersion: 2
guid: eb30bbf806046ba1abf51bdd925e9647
TextureImporter:
internalIDToNameTable: []
externalObjects: {}
serializedVersion: 11
mipmaps:
mipMapMode: 0
enableMipMap: 0
sRGBTexture: 1
linearTexture: 0
fadeOut: 0
borderMipMap: 0
mipMapsPreserveCoverage: 0
alphaTestReferenceValue: 0.5
mipMapFadeDistanceStart: 1
mipMapFadeDistanceEnd: 3
bumpmap:
convertToNormalMap: 0
externalNormalMap: 0
heightScale: 0.25
normalMapFilter: 0
isReadable: 0
streamingMipmaps: 0
streamingMipmapsPriority: 0
vTOnly: 0
grayScaleToAlpha: 0
generateCubemap: 6
cubemapConvolution: 0
seamlessCubemap: 0
textureFormat: 1
maxTextureSize: 2048
textureSettings:
serializedVersion: 2
filterMode: 1
aniso: 1
mipBias: 0
wrapU: 1
wrapV: 1
wrapW: 1
nPOTScale: 0
lightmap: 0
compressionQuality: 50
spriteMode: 1
spriteExtrude: 1
spriteMeshType: 1
alignment: 0
spritePivot: {x: 0.5, y: 0.5}
spritePixelsToUnits: 100
spriteBorder: {x: 0, y: 0, z: 0, w: 0}
spriteGenerateFallbackPhysicsShape: 1
alphaUsage: 1
alphaIsTransparency: 1
spriteTessellationDetail: -1
textureType: 8
textureShape: 1
singleChannelComponent: 0
flipbookRows: 1
flipbookColumns: 1
maxTextureSizeSet: 0
compressionQualitySet: 0
textureFormatSet: 0
ignorePngGamma: 0
applyGammaDecoding: 0
platformSettings:
- serializedVersion: 3
buildTarget: DefaultTexturePlatform
maxTextureSize: 2048
resizeAlgorithm: 0
textureFormat: -1
textureCompression: 1
compressionQuality: 100
crunchedCompression: 1
allowsAlphaSplitting: 0
overridden: 0
androidETC2FallbackOverride: 0
forceMaximumCompressionQuality_BC6H_BC7: 0
- serializedVersion: 3
buildTarget: Standalone
maxTextureSize: 2048
resizeAlgorithm: 0
textureFormat: -1
textureCompression: 1
compressionQuality: 100
crunchedCompression: 1
allowsAlphaSplitting: 0
overridden: 0
androidETC2FallbackOverride: 0
forceMaximumCompressionQuality_BC6H_BC7: 0
- serializedVersion: 3
buildTarget: Android
maxTextureSize: 2048
resizeAlgorithm: 0
textureFormat: -1
textureCompression: 1
compressionQuality: 100
crunchedCompression: 1
allowsAlphaSplitting: 0
overridden: 0
androidETC2FallbackOverride: 0
forceMaximumCompressionQuality_BC6H_BC7: 0
spriteSheet:
serializedVersion: 2
sprites: []
outline: []
physicsShape: []
bones: []
spriteID: 5e97eb03825dee720800000000000000
internalID: 0
vertices: []
indices:
edges: []
weights: []
secondaryTextures: []
spritePackingTag:
pSDRemoveMatte: 0
pSDShowRemoveMatteOption: 0
userData:
assetBundleName:
assetBundleVariant:
Binary file not shown.

After

Width:  |  Height:  |  Size: 825 B

@@ -0,0 +1,120 @@
fileFormatVersion: 2
guid: a9d090601d3e0379b8075998ffd68c0a
TextureImporter:
internalIDToNameTable: []
externalObjects: {}
serializedVersion: 11
mipmaps:
mipMapMode: 0
enableMipMap: 0
sRGBTexture: 1
linearTexture: 0
fadeOut: 0
borderMipMap: 0
mipMapsPreserveCoverage: 0
alphaTestReferenceValue: 0.5
mipMapFadeDistanceStart: 1
mipMapFadeDistanceEnd: 3
bumpmap:
convertToNormalMap: 0
externalNormalMap: 0
heightScale: 0.25
normalMapFilter: 0
isReadable: 0
streamingMipmaps: 0
streamingMipmapsPriority: 0
vTOnly: 0
grayScaleToAlpha: 0
generateCubemap: 6
cubemapConvolution: 0
seamlessCubemap: 0
textureFormat: 1
maxTextureSize: 2048
textureSettings:
serializedVersion: 2
filterMode: 1
aniso: 1
mipBias: 0
wrapU: 1
wrapV: 1
wrapW: 1
nPOTScale: 0
lightmap: 0
compressionQuality: 50
spriteMode: 1
spriteExtrude: 1
spriteMeshType: 0
alignment: 0
spritePivot: {x: 0.5, y: 0.5}
spritePixelsToUnits: 200
spriteBorder: {x: 10, y: 10, z: 10, w: 10}
spriteGenerateFallbackPhysicsShape: 1
alphaUsage: 1
alphaIsTransparency: 1
spriteTessellationDetail: -1
textureType: 8
textureShape: 1
singleChannelComponent: 0
flipbookRows: 1
flipbookColumns: 1
maxTextureSizeSet: 0
compressionQualitySet: 0
textureFormatSet: 0
ignorePngGamma: 0
applyGammaDecoding: 0
platformSettings:
- serializedVersion: 3
buildTarget: DefaultTexturePlatform
maxTextureSize: 2048
resizeAlgorithm: 0
textureFormat: -1
textureCompression: 1
compressionQuality: 100
crunchedCompression: 1
allowsAlphaSplitting: 0
overridden: 0
androidETC2FallbackOverride: 0
forceMaximumCompressionQuality_BC6H_BC7: 0
- serializedVersion: 3
buildTarget: Standalone
maxTextureSize: 2048
resizeAlgorithm: 0
textureFormat: -1
textureCompression: 1
compressionQuality: 100
crunchedCompression: 1
allowsAlphaSplitting: 0
overridden: 0
androidETC2FallbackOverride: 0
forceMaximumCompressionQuality_BC6H_BC7: 0
- serializedVersion: 3
buildTarget: Android
maxTextureSize: 2048
resizeAlgorithm: 0
textureFormat: -1
textureCompression: 1
compressionQuality: 100
crunchedCompression: 1
allowsAlphaSplitting: 0
overridden: 0
androidETC2FallbackOverride: 0
forceMaximumCompressionQuality_BC6H_BC7: 0
spriteSheet:
serializedVersion: 2
sprites: []
outline: []
physicsShape: []
bones: []
spriteID: 5e97eb03825dee720800000000000000
internalID: 0
vertices: []
indices:
edges: []
weights: []
secondaryTextures: []
spritePackingTag:
pSDRemoveMatte: 0
pSDShowRemoveMatteOption: 0
userData:
assetBundleName:
assetBundleVariant:
Binary file not shown.

After

Width:  |  Height:  |  Size: 1.4 KiB

@@ -0,0 +1,120 @@
fileFormatVersion: 2
guid: bc8ea6103cf8330a999ba68b1990c144
TextureImporter:
internalIDToNameTable: []
externalObjects: {}
serializedVersion: 11
mipmaps:
mipMapMode: 0
enableMipMap: 0
sRGBTexture: 1
linearTexture: 0
fadeOut: 0
borderMipMap: 0
mipMapsPreserveCoverage: 0
alphaTestReferenceValue: 0.5
mipMapFadeDistanceStart: 1
mipMapFadeDistanceEnd: 3
bumpmap:
convertToNormalMap: 0
externalNormalMap: 0
heightScale: 0.25
normalMapFilter: 0
isReadable: 0
streamingMipmaps: 0
streamingMipmapsPriority: 0
vTOnly: 0
grayScaleToAlpha: 0
generateCubemap: 6
cubemapConvolution: 0
seamlessCubemap: 0
textureFormat: 1
maxTextureSize: 2048
textureSettings:
serializedVersion: 2
filterMode: 1
aniso: 1
mipBias: 0
wrapU: 1
wrapV: 1
wrapW: 1
nPOTScale: 0
lightmap: 0
compressionQuality: 50
spriteMode: 1
spriteExtrude: 1
spriteMeshType: 1
alignment: 0
spritePivot: {x: 0.5, y: 0.5}
spritePixelsToUnits: 100
spriteBorder: {x: 0, y: 0, z: 0, w: 0}
spriteGenerateFallbackPhysicsShape: 1
alphaUsage: 1
alphaIsTransparency: 1
spriteTessellationDetail: -1
textureType: 8
textureShape: 1
singleChannelComponent: 0
flipbookRows: 1
flipbookColumns: 1
maxTextureSizeSet: 0
compressionQualitySet: 0
textureFormatSet: 0
ignorePngGamma: 0
applyGammaDecoding: 0
platformSettings:
- serializedVersion: 3
buildTarget: DefaultTexturePlatform
maxTextureSize: 2048
resizeAlgorithm: 0
textureFormat: -1
textureCompression: 1
compressionQuality: 100
crunchedCompression: 1
allowsAlphaSplitting: 0
overridden: 0
androidETC2FallbackOverride: 0
forceMaximumCompressionQuality_BC6H_BC7: 0
- serializedVersion: 3
buildTarget: Standalone
maxTextureSize: 2048
resizeAlgorithm: 0
textureFormat: -1
textureCompression: 1
compressionQuality: 100
crunchedCompression: 1
allowsAlphaSplitting: 0
overridden: 0
androidETC2FallbackOverride: 0
forceMaximumCompressionQuality_BC6H_BC7: 0
- serializedVersion: 3
buildTarget: Android
maxTextureSize: 2048
resizeAlgorithm: 0
textureFormat: -1
textureCompression: 1
compressionQuality: 100
crunchedCompression: 1
allowsAlphaSplitting: 0
overridden: 0
androidETC2FallbackOverride: 0
forceMaximumCompressionQuality_BC6H_BC7: 0
spriteSheet:
serializedVersion: 2
sprites: []
outline: []
physicsShape: []
bones: []
spriteID: 5e97eb03825dee720800000000000000
internalID: 0
vertices: []
indices:
edges: []
weights: []
secondaryTextures: []
spritePackingTag:
pSDRemoveMatte: 0
pSDShowRemoveMatteOption: 0
userData:
assetBundleName:
assetBundleVariant:
Binary file not shown.

After

Width:  |  Height:  |  Size: 270 B

@@ -0,0 +1,120 @@
fileFormatVersion: 2
guid: 510b2bfc58b13bddd82690444d29a7f1
TextureImporter:
internalIDToNameTable: []
externalObjects: {}
serializedVersion: 11
mipmaps:
mipMapMode: 0
enableMipMap: 0
sRGBTexture: 1
linearTexture: 0
fadeOut: 0
borderMipMap: 0
mipMapsPreserveCoverage: 0
alphaTestReferenceValue: 0.5
mipMapFadeDistanceStart: 1
mipMapFadeDistanceEnd: 3
bumpmap:
convertToNormalMap: 0
externalNormalMap: 0
heightScale: 0.25
normalMapFilter: 0
isReadable: 0
streamingMipmaps: 0
streamingMipmapsPriority: 0
vTOnly: 0
grayScaleToAlpha: 0
generateCubemap: 6
cubemapConvolution: 0
seamlessCubemap: 0
textureFormat: 1
maxTextureSize: 2048
textureSettings:
serializedVersion: 2
filterMode: 1
aniso: 1
mipBias: 0
wrapU: 1
wrapV: 1
wrapW: 1
nPOTScale: 0
lightmap: 0
compressionQuality: 50
spriteMode: 1
spriteExtrude: 1
spriteMeshType: 0
alignment: 0
spritePivot: {x: 0.5, y: 0.5}
spritePixelsToUnits: 200
spriteBorder: {x: 10, y: 10, z: 10, w: 10}
spriteGenerateFallbackPhysicsShape: 1
alphaUsage: 1
alphaIsTransparency: 1
spriteTessellationDetail: -1
textureType: 8
textureShape: 1
singleChannelComponent: 0
flipbookRows: 1
flipbookColumns: 1
maxTextureSizeSet: 0
compressionQualitySet: 0
textureFormatSet: 0
ignorePngGamma: 0
applyGammaDecoding: 0
platformSettings:
- serializedVersion: 3
buildTarget: DefaultTexturePlatform
maxTextureSize: 2048
resizeAlgorithm: 0
textureFormat: -1
textureCompression: 1
compressionQuality: 100
crunchedCompression: 1
allowsAlphaSplitting: 0
overridden: 0
androidETC2FallbackOverride: 0
forceMaximumCompressionQuality_BC6H_BC7: 0
- serializedVersion: 3
buildTarget: Standalone
maxTextureSize: 2048
resizeAlgorithm: 0
textureFormat: -1
textureCompression: 1
compressionQuality: 100
crunchedCompression: 1
allowsAlphaSplitting: 0
overridden: 0
androidETC2FallbackOverride: 0
forceMaximumCompressionQuality_BC6H_BC7: 0
- serializedVersion: 3
buildTarget: Android
maxTextureSize: 2048
resizeAlgorithm: 0
textureFormat: -1
textureCompression: 1
compressionQuality: 100
crunchedCompression: 1
allowsAlphaSplitting: 0
overridden: 0
androidETC2FallbackOverride: 0
forceMaximumCompressionQuality_BC6H_BC7: 0
spriteSheet:
serializedVersion: 2
sprites: []
outline: []
physicsShape: []
bones: []
spriteID: 5e97eb03825dee720800000000000000
internalID: 0
vertices: []
indices:
edges: []
weights: []
secondaryTextures: []
spritePackingTag:
pSDRemoveMatte: 0
pSDShowRemoveMatteOption: 0
userData:
assetBundleName:
assetBundleVariant:
Binary file not shown.

After

Width:  |  Height:  |  Size: 740 B

@@ -0,0 +1,120 @@
fileFormatVersion: 2
guid: 63bb215422fe83002acfe2f01232904c
TextureImporter:
internalIDToNameTable: []
externalObjects: {}
serializedVersion: 11
mipmaps:
mipMapMode: 0
enableMipMap: 0
sRGBTexture: 1
linearTexture: 0
fadeOut: 0
borderMipMap: 0
mipMapsPreserveCoverage: 0
alphaTestReferenceValue: 0.5
mipMapFadeDistanceStart: 1
mipMapFadeDistanceEnd: 3
bumpmap:
convertToNormalMap: 0
externalNormalMap: 0
heightScale: 0.25
normalMapFilter: 0
isReadable: 0
streamingMipmaps: 0
streamingMipmapsPriority: 0
vTOnly: 0
grayScaleToAlpha: 0
generateCubemap: 6
cubemapConvolution: 0
seamlessCubemap: 0
textureFormat: 1
maxTextureSize: 2048
textureSettings:
serializedVersion: 2
filterMode: 1
aniso: 1
mipBias: 0
wrapU: 1
wrapV: 1
wrapW: 1
nPOTScale: 0
lightmap: 0
compressionQuality: 50
spriteMode: 1
spriteExtrude: 1
spriteMeshType: 0
alignment: 0
spritePivot: {x: 0.5, y: 0.5}
spritePixelsToUnits: 200
spriteBorder: {x: 10, y: 10, z: 10, w: 10}
spriteGenerateFallbackPhysicsShape: 1
alphaUsage: 1
alphaIsTransparency: 1
spriteTessellationDetail: -1
textureType: 8
textureShape: 1
singleChannelComponent: 0
flipbookRows: 1
flipbookColumns: 1
maxTextureSizeSet: 0
compressionQualitySet: 0
textureFormatSet: 0
ignorePngGamma: 0
applyGammaDecoding: 0
platformSettings:
- serializedVersion: 3
buildTarget: DefaultTexturePlatform
maxTextureSize: 2048
resizeAlgorithm: 0
textureFormat: -1
textureCompression: 1
compressionQuality: 100
crunchedCompression: 1
allowsAlphaSplitting: 0
overridden: 0
androidETC2FallbackOverride: 0
forceMaximumCompressionQuality_BC6H_BC7: 0
- serializedVersion: 3
buildTarget: Standalone
maxTextureSize: 2048
resizeAlgorithm: 0
textureFormat: -1
textureCompression: 1
compressionQuality: 100
crunchedCompression: 1
allowsAlphaSplitting: 0
overridden: 0
androidETC2FallbackOverride: 0
forceMaximumCompressionQuality_BC6H_BC7: 0
- serializedVersion: 3
buildTarget: Android
maxTextureSize: 2048
resizeAlgorithm: 0
textureFormat: -1
textureCompression: 1
compressionQuality: 100
crunchedCompression: 1
allowsAlphaSplitting: 0
overridden: 0
androidETC2FallbackOverride: 0
forceMaximumCompressionQuality_BC6H_BC7: 0
spriteSheet:
serializedVersion: 2
sprites: []
outline: []
physicsShape: []
bones: []
spriteID: 5e97eb03825dee720800000000000000
internalID: 0
vertices: []
indices:
edges: []
weights: []
secondaryTextures: []
spritePackingTag:
pSDRemoveMatte: 0
pSDShowRemoveMatteOption: 0
userData:
assetBundleName:
assetBundleVariant:
+102
View File
@@ -0,0 +1,102 @@
#if UNITY_EDITOR
using System;
using System.Diagnostics;
using System.IO;
using System.Linq;
using UnityEditor;
using Debug = UnityEngine.Debug;
internal static class Build
{
public static BuildTarget[] Targets { get; } =
{
BuildTarget.StandaloneWindows,
BuildTarget.Android,
};
public static Compression Compression => Compression.LZMA;
public static string OutputPath { get; } = Path.Combine("..", "Reactor", "Assets");
public static string AssetBundlesPath { get; } = Path.Combine("Assets", "AssetBundles");
public static string TempPath { get; } = Path.Combine("Temp", "AssetBundles");
[MenuItem("File/Build Asset Bundles")]
public static void BuildAssetBundles()
{
Directory.CreateDirectory(TempPath);
var ignoredExtensions = new[] { ".meta", ".manifest", ".dll", ".cs", ".exe", ".tps" };
var builds = Directory.GetDirectories(AssetBundlesPath)
.Select(directoryPath => new AssetBundleBuild
{
assetBundleName = Path.GetFileName(directoryPath),
assetNames = Directory.GetFiles(directoryPath, "*", SearchOption.AllDirectories).Where(p => !ignoredExtensions.Contains(Path.GetExtension(p))).ToArray(),
})
.ToArray();
Debug.Log($"Building {builds.Length} asset bundle(s) ({string.Join(", ", builds.Select(b => b.assetBundleName))})");
var options = BuildAssetBundleOptions.StrictMode;
switch (Compression)
{
case Compression.None:
options |= BuildAssetBundleOptions.UncompressedAssetBundle;
break;
case Compression.LZ4:
options |= BuildAssetBundleOptions.ChunkBasedCompression;
break;
}
foreach (var target in Targets)
{
var tempPath = Path.Combine(TempPath, target.ToString());
Directory.CreateDirectory(tempPath);
var stopwatch = Stopwatch.StartNew();
var manifest = BuildPipeline.BuildAssetBundles(tempPath, builds, options, target);
Debug.Log($"Built asset bundle(s) for {target} in {stopwatch.Elapsed}");
foreach (var assetBundleName in manifest.GetAllAssetBundles())
{
var destinationPath = Path.Combine(OutputPath, $"{assetBundleName}-{GetTargetName(target)}.bundle");
File.Delete(destinationPath);
File.Copy(Path.Combine(tempPath, assetBundleName), destinationPath);
}
}
}
private static string GetTargetName(BuildTarget target)
{
return target switch
{
BuildTarget.StandaloneWindows => "win-x86",
BuildTarget.StandaloneWindows64 => "win-x64",
BuildTarget.Android => "android",
BuildTarget.StandaloneLinux64 => "linux-x64",
_ => throw new ArgumentOutOfRangeException(nameof(target), target, null),
};
}
}
internal enum Compression
{
/// <summary>
/// Worst size, best load speed
/// </summary>
None,
/// <summary>
/// Best size, worst load speed
/// </summary>
LZMA,
/// <summary>
/// Okay size, okay load speed
/// </summary>
LZ4,
}
#endif
+11
View File
@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: d785823c2752b6812b292c93aa323bfa
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
+40
View File
@@ -0,0 +1,40 @@
{
"dependencies": {
"com.unity.2d.sprite": "1.0.0",
"com.unity.ide.rider": "2.0.7",
"com.unity.ide.visualstudio": "2.0.16",
"com.unity.ide.vscode": "1.2.5",
"com.unity.toolchain.linux-x86_64": "2.0.2",
"com.unity.modules.ai": "1.0.0",
"com.unity.modules.androidjni": "1.0.0",
"com.unity.modules.animation": "1.0.0",
"com.unity.modules.assetbundle": "1.0.0",
"com.unity.modules.audio": "1.0.0",
"com.unity.modules.cloth": "1.0.0",
"com.unity.modules.director": "1.0.0",
"com.unity.modules.imageconversion": "1.0.0",
"com.unity.modules.imgui": "1.0.0",
"com.unity.modules.jsonserialize": "1.0.0",
"com.unity.modules.particlesystem": "1.0.0",
"com.unity.modules.physics": "1.0.0",
"com.unity.modules.physics2d": "1.0.0",
"com.unity.modules.screencapture": "1.0.0",
"com.unity.modules.terrain": "1.0.0",
"com.unity.modules.terrainphysics": "1.0.0",
"com.unity.modules.tilemap": "1.0.0",
"com.unity.modules.ui": "1.0.0",
"com.unity.modules.uielements": "1.0.0",
"com.unity.modules.umbra": "1.0.0",
"com.unity.modules.unityanalytics": "1.0.0",
"com.unity.modules.unitywebrequest": "1.0.0",
"com.unity.modules.unitywebrequestassetbundle": "1.0.0",
"com.unity.modules.unitywebrequestaudio": "1.0.0",
"com.unity.modules.unitywebrequesttexture": "1.0.0",
"com.unity.modules.unitywebrequestwww": "1.0.0",
"com.unity.modules.vehicles": "1.0.0",
"com.unity.modules.video": "1.0.0",
"com.unity.modules.vr": "1.0.0",
"com.unity.modules.wind": "1.0.0",
"com.unity.modules.xr": "1.0.0"
}
}
+333
View File
@@ -0,0 +1,333 @@
{
"dependencies": {
"com.unity.2d.sprite": {
"version": "1.0.0",
"depth": 0,
"source": "builtin",
"dependencies": {}
},
"com.unity.ext.nunit": {
"version": "1.0.6",
"depth": 2,
"source": "registry",
"dependencies": {},
"url": "https://packages.unity.com"
},
"com.unity.ide.rider": {
"version": "2.0.7",
"depth": 0,
"source": "registry",
"dependencies": {
"com.unity.test-framework": "1.1.1"
},
"url": "https://packages.unity.com"
},
"com.unity.ide.visualstudio": {
"version": "2.0.16",
"depth": 0,
"source": "registry",
"dependencies": {
"com.unity.test-framework": "1.1.9"
},
"url": "https://packages.unity.com"
},
"com.unity.ide.vscode": {
"version": "1.2.5",
"depth": 0,
"source": "registry",
"dependencies": {},
"url": "https://packages.unity.com"
},
"com.unity.sysroot": {
"version": "2.0.3",
"depth": 1,
"source": "registry",
"dependencies": {},
"url": "https://packages.unity.com"
},
"com.unity.sysroot.linux-x86_64": {
"version": "2.0.2",
"depth": 1,
"source": "registry",
"dependencies": {
"com.unity.sysroot": "2.0.3"
},
"url": "https://packages.unity.com"
},
"com.unity.test-framework": {
"version": "1.1.29",
"depth": 1,
"source": "registry",
"dependencies": {
"com.unity.ext.nunit": "1.0.6",
"com.unity.modules.imgui": "1.0.0",
"com.unity.modules.jsonserialize": "1.0.0"
},
"url": "https://packages.unity.com"
},
"com.unity.toolchain.linux-x86_64": {
"version": "2.0.2",
"depth": 0,
"source": "registry",
"dependencies": {
"com.unity.sysroot": "2.0.3",
"com.unity.sysroot.linux-x86_64": "2.0.2"
},
"url": "https://packages.unity.com"
},
"com.unity.modules.ai": {
"version": "1.0.0",
"depth": 0,
"source": "builtin",
"dependencies": {}
},
"com.unity.modules.androidjni": {
"version": "1.0.0",
"depth": 0,
"source": "builtin",
"dependencies": {}
},
"com.unity.modules.animation": {
"version": "1.0.0",
"depth": 0,
"source": "builtin",
"dependencies": {}
},
"com.unity.modules.assetbundle": {
"version": "1.0.0",
"depth": 0,
"source": "builtin",
"dependencies": {}
},
"com.unity.modules.audio": {
"version": "1.0.0",
"depth": 0,
"source": "builtin",
"dependencies": {}
},
"com.unity.modules.cloth": {
"version": "1.0.0",
"depth": 0,
"source": "builtin",
"dependencies": {
"com.unity.modules.physics": "1.0.0"
}
},
"com.unity.modules.director": {
"version": "1.0.0",
"depth": 0,
"source": "builtin",
"dependencies": {
"com.unity.modules.audio": "1.0.0",
"com.unity.modules.animation": "1.0.0"
}
},
"com.unity.modules.imageconversion": {
"version": "1.0.0",
"depth": 0,
"source": "builtin",
"dependencies": {}
},
"com.unity.modules.imgui": {
"version": "1.0.0",
"depth": 0,
"source": "builtin",
"dependencies": {}
},
"com.unity.modules.jsonserialize": {
"version": "1.0.0",
"depth": 0,
"source": "builtin",
"dependencies": {}
},
"com.unity.modules.particlesystem": {
"version": "1.0.0",
"depth": 0,
"source": "builtin",
"dependencies": {}
},
"com.unity.modules.physics": {
"version": "1.0.0",
"depth": 0,
"source": "builtin",
"dependencies": {}
},
"com.unity.modules.physics2d": {
"version": "1.0.0",
"depth": 0,
"source": "builtin",
"dependencies": {}
},
"com.unity.modules.screencapture": {
"version": "1.0.0",
"depth": 0,
"source": "builtin",
"dependencies": {
"com.unity.modules.imageconversion": "1.0.0"
}
},
"com.unity.modules.subsystems": {
"version": "1.0.0",
"depth": 1,
"source": "builtin",
"dependencies": {
"com.unity.modules.jsonserialize": "1.0.0"
}
},
"com.unity.modules.terrain": {
"version": "1.0.0",
"depth": 0,
"source": "builtin",
"dependencies": {}
},
"com.unity.modules.terrainphysics": {
"version": "1.0.0",
"depth": 0,
"source": "builtin",
"dependencies": {
"com.unity.modules.physics": "1.0.0",
"com.unity.modules.terrain": "1.0.0"
}
},
"com.unity.modules.tilemap": {
"version": "1.0.0",
"depth": 0,
"source": "builtin",
"dependencies": {
"com.unity.modules.physics2d": "1.0.0"
}
},
"com.unity.modules.ui": {
"version": "1.0.0",
"depth": 0,
"source": "builtin",
"dependencies": {}
},
"com.unity.modules.uielements": {
"version": "1.0.0",
"depth": 0,
"source": "builtin",
"dependencies": {
"com.unity.modules.ui": "1.0.0",
"com.unity.modules.imgui": "1.0.0",
"com.unity.modules.jsonserialize": "1.0.0",
"com.unity.modules.uielementsnative": "1.0.0"
}
},
"com.unity.modules.uielementsnative": {
"version": "1.0.0",
"depth": 1,
"source": "builtin",
"dependencies": {
"com.unity.modules.ui": "1.0.0",
"com.unity.modules.imgui": "1.0.0",
"com.unity.modules.jsonserialize": "1.0.0"
}
},
"com.unity.modules.umbra": {
"version": "1.0.0",
"depth": 0,
"source": "builtin",
"dependencies": {}
},
"com.unity.modules.unityanalytics": {
"version": "1.0.0",
"depth": 0,
"source": "builtin",
"dependencies": {
"com.unity.modules.unitywebrequest": "1.0.0",
"com.unity.modules.jsonserialize": "1.0.0"
}
},
"com.unity.modules.unitywebrequest": {
"version": "1.0.0",
"depth": 0,
"source": "builtin",
"dependencies": {}
},
"com.unity.modules.unitywebrequestassetbundle": {
"version": "1.0.0",
"depth": 0,
"source": "builtin",
"dependencies": {
"com.unity.modules.assetbundle": "1.0.0",
"com.unity.modules.unitywebrequest": "1.0.0"
}
},
"com.unity.modules.unitywebrequestaudio": {
"version": "1.0.0",
"depth": 0,
"source": "builtin",
"dependencies": {
"com.unity.modules.unitywebrequest": "1.0.0",
"com.unity.modules.audio": "1.0.0"
}
},
"com.unity.modules.unitywebrequesttexture": {
"version": "1.0.0",
"depth": 0,
"source": "builtin",
"dependencies": {
"com.unity.modules.unitywebrequest": "1.0.0",
"com.unity.modules.imageconversion": "1.0.0"
}
},
"com.unity.modules.unitywebrequestwww": {
"version": "1.0.0",
"depth": 0,
"source": "builtin",
"dependencies": {
"com.unity.modules.unitywebrequest": "1.0.0",
"com.unity.modules.unitywebrequestassetbundle": "1.0.0",
"com.unity.modules.unitywebrequestaudio": "1.0.0",
"com.unity.modules.audio": "1.0.0",
"com.unity.modules.assetbundle": "1.0.0",
"com.unity.modules.imageconversion": "1.0.0"
}
},
"com.unity.modules.vehicles": {
"version": "1.0.0",
"depth": 0,
"source": "builtin",
"dependencies": {
"com.unity.modules.physics": "1.0.0"
}
},
"com.unity.modules.video": {
"version": "1.0.0",
"depth": 0,
"source": "builtin",
"dependencies": {
"com.unity.modules.audio": "1.0.0",
"com.unity.modules.ui": "1.0.0",
"com.unity.modules.unitywebrequest": "1.0.0"
}
},
"com.unity.modules.vr": {
"version": "1.0.0",
"depth": 0,
"source": "builtin",
"dependencies": {
"com.unity.modules.jsonserialize": "1.0.0",
"com.unity.modules.physics": "1.0.0",
"com.unity.modules.xr": "1.0.0"
}
},
"com.unity.modules.wind": {
"version": "1.0.0",
"depth": 0,
"source": "builtin",
"dependencies": {}
},
"com.unity.modules.xr": {
"version": "1.0.0",
"depth": 0,
"source": "builtin",
"dependencies": {
"com.unity.modules.physics": "1.0.0",
"com.unity.modules.jsonserialize": "1.0.0",
"com.unity.modules.subsystems": "1.0.0"
}
}
}
}
@@ -0,0 +1,2 @@
m_EditorVersion: 2020.3.22f1
m_EditorVersionWithRevision: 2020.3.22f1 (e1a7f79fd887)
+25
View File
@@ -0,0 +1,25 @@
#!/bin/bash
UNITY_VERSION=2020.3.22f1
if [[ ! -v UNITY_PATH ]]; then
if command -v unityhub &>/dev/null; then
echo "Trying to get unity path from unityhub..."
UNITYHUB_INSTALL_PATH=$(unityhub --headless install-path)
UNITY_PATH="$UNITYHUB_INSTALL_PATH/$UNITY_VERSION/Editor/Unity"
if [[ ! -f $UNITY_PATH ]]; then
echo "Unity $UNITY_VERSION is not installed"
exit 1
fi
else
echo "UNITY_PATH is not set"
exit 1
fi
fi
echo "UNITY_PATH = $UNITY_PATH"
rm Library -rf # TODO figure out why having Library cached makes invalid bundles in batchmode
$UNITY_PATH -batchmode -nographics -quit -logFile "-" -projectPath $pwd -executeMethod Build.BuildAssetBundles
@@ -0,0 +1,97 @@
using System;
using System.Collections.Generic;
using System.IO;
using BenchmarkDotNet.Attributes;
using BenchmarkDotNet.Configs;
using BenchmarkDotNet.Jobs;
using BepInEx;
using Il2CppInterop.Runtime.InteropTypes.Arrays;
using Reactor.Utilities;
using Reactor.Utilities.Extensions;
using UnityEngine;
namespace Reactor.Benchmarks;
[MemoryDiagnoser]
[StopOnFirstError, Config(typeof(Config))]
public class AssetBundleBenchmarks
{
private class Config : ManualConfig
{
public Config()
{
AddJob(Job.ShortRun.WithLaunchCount(1).WithWarmupCount(1).WithIterationCount(10).WithToolchain(SingleThreadedInProcessEmitToolchain.Instance));
}
}
[ParamsSource(nameof(ValuesForAssetBundleName))]
public string AssetBundleFileName { get; set; } = null!;
public static IEnumerable<string> ValuesForAssetBundleName()
{
yield return $"default-{AssetBundleManager.TargetName}{AssetBundleManager.BundleExtension}";
// yield return "submerged";
}
[IterationSetup]
public void IterationSetup()
{
AssetBundle.UnloadAllAssetBundles(true);
}
private AssetBundle LoadAll(AssetBundle assetBundle)
{
if (assetBundle == null) throw new ArgumentNullException(nameof(assetBundle));
assetBundle.LoadAllAssets();
return assetBundle;
}
private Stream GetResourceStream()
{
return typeof(ReactorPlugin).Assembly.GetManifestResourceStream("Reactor.Assets." + AssetBundleFileName)!;
}
[Benchmark]
public AssetBundle LoadFromStream()
{
using var stream = GetResourceStream();
return LoadAll(AssetBundle.LoadFromStream(stream.AsIl2Cpp()));
}
[Benchmark]
public AssetBundle LoadFromMemory_ReadFully()
{
using var stream = GetResourceStream();
return LoadAll(AssetBundle.LoadFromMemory(stream.ReadFully()));
}
[Benchmark]
public unsafe AssetBundle LoadFromMemory_ReadFullyFastCopy()
{
using var stream = GetResourceStream();
var array = stream.ReadFully();
var il2CppArray = new Il2CppStructArray<byte>(array.Length);
fixed (byte* arrayPtr = array) { Buffer.MemoryCopy(arrayPtr, IntPtr.Add(il2CppArray.Pointer, 4 * IntPtr.Size).ToPointer(), il2CppArray.Length, array.Length); }
return LoadAll(AssetBundle.LoadFromMemory(il2CppArray));
}
[Benchmark]
public AssetBundle LoadFromMemory_Span()
{
using var stream = GetResourceStream();
var length = (int) stream.Length;
var array = new Il2CppStructArray<byte>(length);
if (stream.Read(array.ToSpan()) < length) throw new IOException("Failed to read in full");
return LoadAll(AssetBundle.LoadFromMemory(array));
}
[Benchmark]
public AssetBundle LoadFromFile()
{
return LoadAll(AssetBundle.LoadFromFile(Path.Combine(Paths.PluginPath, AssetBundleFileName)));
}
}
+24
View File
@@ -0,0 +1,24 @@
using System.Diagnostics;
using BenchmarkDotNet.Running;
using BepInEx;
using BepInEx.Unity.IL2CPP;
namespace Reactor.Benchmarks;
[BepInAutoPlugin("gg.reactor.benchmarks")]
[BepInProcess("Among Us.exe")]
[BepInDependency(ReactorPlugin.Id)]
public partial class BenchmarksPlugin : BasePlugin
{
public override void Load()
{
try
{
BenchmarkRunner.Run<AssetBundleBenchmarks>();
}
finally
{
Process.GetCurrentProcess().Kill();
}
}
}
@@ -0,0 +1,15 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<Version>0.1.0</Version>
<Authors>NuclearPowered</Authors>
<EnableDynamicLoading>true</EnableDynamicLoading>
<SatelliteResourceLanguages>en-US</SatelliteResourceLanguages>
</PropertyGroup>
<ItemGroup>
<ProjectReference Include="..\Reactor\Reactor.csproj" Private="false" />
<PackageReference Include="BenchmarkDotNet" Version="0.13.2" />
</ItemGroup>
<Import Project="../AmongUs.props" />
</Project>
@@ -0,0 +1,54 @@
#pragma warning disable SA1611, SA1615
using BenchmarkDotNet.Engines;
using BenchmarkDotNet.Loggers;
using BenchmarkDotNet.Toolchains;
using BenchmarkDotNet.Toolchains.InProcess;
using BenchmarkDotNet.Toolchains.InProcess.Emit;
using BenchmarkDotNet.Toolchains.InProcess.Emit.Implementation;
using BenchmarkDotNet.Toolchains.Parameters;
using BenchmarkDotNet.Toolchains.Results;
using HarmonyLib;
namespace Reactor.Benchmarks;
public class SingleThreadedInProcessEmitToolchain : Toolchain
{
public static readonly IToolchain Instance = new SingleThreadedInProcessEmitToolchain(true);
public SingleThreadedInProcessEmitToolchain(bool logOutput)
: base(nameof(SingleThreadedInProcessEmitToolchain), new InProcessEmitGenerator(), new InProcessEmitBuilder(), new SingleThreadedInProcessEmitExecutor(logOutput))
{
}
}
public class SingleThreadedInProcessEmitExecutor : IExecutor
{
/// <summary>Initializes a new instance of the <see cref="SingleThreadedInProcessEmitExecutor" /> class.</summary>
/// <param name="logOutput"><c>true</c> if the output should be logged.</param>
public SingleThreadedInProcessEmitExecutor(bool logOutput)
{
LogOutput = logOutput;
}
/// <summary>Gets a value indicating whether the output should be logged.</summary>
/// <value><c>true</c> if the output should be logged; otherwise, <c>false</c>.</value>
public bool LogOutput { get; }
/// <summary>Executes the specified benchmark.</summary>
public ExecuteResult Execute(ExecuteParameters executeParameters)
{
var hostLogger = LogOutput ? executeParameters.Logger : NullLogger.Instance;
var host = new InProcessHost(executeParameters.BenchmarkCase, hostLogger, executeParameters.Diagnoser);
var exitCode = ExecuteCore(host, executeParameters);
return ((ExecuteResult) AccessTools.Method(typeof(ExecuteResult), "FromRunResults").Invoke(null, new object[] { host.RunResults, exitCode })!)!;
}
private int ExecuteCore(IHost host, ExecuteParameters parameters)
{
var generatedAssembly = ((InProcessEmitArtifactsPath) parameters.BuildResult.ArtifactsPaths).GeneratedAssembly;
return RunnableProgram.Run(parameters.BenchmarkId, generatedAssembly, parameters.BenchmarkCase, host);
}
}
File diff suppressed because it is too large. Load diff
+96 -107
View File
@@ -1,130 +1,119 @@
using System;
using System.Linq;
using AmongUs.Data;
using AmongUs.GameOptions;
using BepInEx;
using BepInEx.IL2CPP;
using BepInEx.Unity.IL2CPP;
using HarmonyLib;
using Il2CppInterop.Runtime.Attributes;
using Il2CppInterop.Runtime.InteropTypes.Arrays;
using InnerNet;
using Reactor.Extensions;
using UnhollowerBaseLib;
using UnhollowerBaseLib.Attributes;
using Reactor.Utilities.Attributes;
using Reactor.Utilities.ImGui;
using UnityEngine;
namespace Reactor.Debugger
namespace Reactor.Debugger;
[BepInAutoPlugin("gg.reactor.debugger")]
[BepInProcess("Among Us.exe")]
[BepInDependency(ReactorPlugin.Id)]
public partial class DebuggerPlugin : BasePlugin
{
[BepInPlugin(Id)]
[BepInProcess("Among Us.exe")]
[BepInDependency(ReactorPlugin.Id)]
[ReactorPluginSide(PluginSide.ClientOnly)]
public class DebuggerPlugin : BasePlugin
public Harmony Harmony { get; } = new(Id);
public DebuggerComponent Component { get; private set; } = null!;
public override void Load()
{
public const string Id = "gg.reactor.debugger";
Component = this.AddComponent<DebuggerComponent>();
public Harmony Harmony { get; } = new Harmony(Id);
public DebuggerComponent Component { get; private set; }
GameOptionsData.MaxImpostors = GameOptionsData.RecommendedImpostors = Enumerable.Repeat((int) byte.MaxValue, byte.MaxValue).ToArray();
GameOptionsData.MinPlayers = Enumerable.Repeat(1, 4).ToArray();
public override void Load()
Harmony.PatchAll();
}
[RegisterInIl2Cpp]
public class DebuggerComponent : MonoBehaviour
{
[HideFromIl2Cpp]
public bool DisableGameEnd { get; set; }
[HideFromIl2Cpp]
public DragWindow TestWindow { get; }
public DebuggerComponent(IntPtr ptr) : base(ptr)
{
var gameObject = new GameObject(nameof(DebuggerPlugin)).DontDestroy();
Component = gameObject.AddComponent<DebuggerComponent>();
TestWindow = new DragWindow(new Rect(20, 20, 0, 0), "Debugger", () =>
{
GUILayout.Label("Name: " + DataManager.Player.Customization.Name);
DisableGameEnd = GUILayout.Toggle(DisableGameEnd, "Disable game end");
GameOptionsData.MaxImpostors = GameOptionsData.RecommendedImpostors = Enumerable.Repeat((int) byte.MaxValue, byte.MaxValue).ToArray();
GameOptionsData.MinPlayers = Enumerable.Repeat(1, 4).ToArray();
if (ShipStatus.Instance && AmongUsClient.Instance.AmHost)
{
if (GUILayout.Button("Force game end"))
{
ShipStatus.Instance.enabled = false;
GameManager.Instance.RpcEndGame(GameOverReason.ImpostorDisconnect, false);
}
Harmony.PatchAll();
if (GUILayout.Button("Call a meeting"))
{
PlayerControl.LocalPlayer.CmdReportDeadBody(null);
}
}
if (TutorialManager.InstanceExists && PlayerControl.LocalPlayer)
{
var data = PlayerControl.LocalPlayer.Data;
var newIsImpostor = GUILayout.Toggle(data.Role.IsImpostor, "Is Impostor");
if (data.Role.IsImpostor != newIsImpostor)
{
PlayerControl.LocalPlayer.RpcSetRole(newIsImpostor ? RoleTypes.Impostor : RoleTypes.Crewmate);
}
if (GUILayout.Button("Spawn a dummy"))
{
var playerControl = Instantiate(TutorialManager.Instance.PlayerPrefab);
var i = playerControl.PlayerId = (byte) GameData.Instance.GetAvailableId();
GameData.Instance.AddPlayer(playerControl);
AmongUsClient.Instance.Spawn(playerControl, -2, SpawnFlags.None);
playerControl.transform.position = PlayerControl.LocalPlayer.transform.position;
playerControl.GetComponent<DummyBehaviour>().enabled = true;
playerControl.NetTransform.enabled = false;
playerControl.SetName($"{TranslationController.Instance.GetString(StringNames.Dummy, Array.Empty<Il2CppSystem.Object>())} {i}");
var color = (byte) (i % Palette.PlayerColors.Length);
playerControl.SetColor(color);
playerControl.SetHat(HatManager.Instance.allHats[i % HatManager.Instance.allHats.Count].ProdId, playerControl.Data.DefaultOutfit.ColorId);
playerControl.SetPet(HatManager.Instance.allPets[i % HatManager.Instance.allPets.Count].ProdId);
playerControl.SetSkin(HatManager.Instance.allSkins[i % HatManager.Instance.allSkins.Count].ProdId, color);
GameData.Instance.RpcSetTasks(playerControl.PlayerId, new Il2CppStructArray<byte>(0));
}
}
if (PlayerControl.LocalPlayer)
{
var position = PlayerControl.LocalPlayer.transform.position;
GUILayout.Label($"x: {position.x}");
GUILayout.Label($"y: {position.y}");
}
})
{
Enabled = false,
};
}
[RegisterInIl2Cpp]
public class DebuggerComponent : MonoBehaviour
private void Update()
{
[HideFromIl2Cpp]
public bool DisableGameEnd { get; set; }
[HideFromIl2Cpp]
public DragWindow TestWindow { get; }
public DebuggerComponent(IntPtr ptr) : base(ptr)
if (Input.GetKeyDown(KeyCode.F1))
{
TestWindow = new DragWindow(new Rect(20, 20, 0, 0), "Debugger", () =>
{
GUILayout.Label("Name: " + SaveManager.PlayerName, new Il2CppReferenceArray<GUILayoutOption>(0));
DisableGameEnd = GUILayout.Toggle(DisableGameEnd, "Disable game end", new Il2CppReferenceArray<GUILayoutOption>(0));
if (ShipStatus.Instance && AmongUsClient.Instance.AmHost)
{
if (GUILayout.Button("Force game end", new Il2CppReferenceArray<GUILayoutOption>(0)))
{
ShipStatus.Instance.enabled = false;
ShipStatus.RpcEndGame(GameOverReason.ImpostorDisconnect, false);
}
if (GUILayout.Button("Call a meeting", new Il2CppReferenceArray<GUILayoutOption>(0)))
{
PlayerControl.LocalPlayer.CmdReportDeadBody(null);
}
}
if (TutorialManager.InstanceExists && PlayerControl.LocalPlayer)
{
var data = PlayerControl.LocalPlayer.Data;
var newIsImpostor = GUILayout.Toggle(data.IsImpostor, "Is Impostor", new Il2CppReferenceArray<GUILayoutOption>(0));
if (data.IsImpostor != newIsImpostor)
{
if (newIsImpostor)
{
PlayerControl.LocalPlayer.RpcSetInfected(new[]
{
data
});
}
else
{
PlayerControl.LocalPlayer.RemoveInfected();
}
}
if (GUILayout.Button("Spawn a dummy", new Il2CppReferenceArray<GUILayoutOption>(0)))
{
var playerControl = Instantiate(TutorialManager.Instance.PlayerPrefab);
var i = playerControl.PlayerId = (byte) GameData.Instance.GetAvailableId();
GameData.Instance.AddPlayer(playerControl);
AmongUsClient.Instance.Spawn(playerControl, -2, SpawnFlags.None);
playerControl.transform.position = PlayerControl.LocalPlayer.transform.position;
playerControl.GetComponent<DummyBehaviour>().enabled = true;
playerControl.NetTransform.enabled = false;
playerControl.SetName($"{TranslationController.Instance.GetString(StringNames.Dummy, Array.Empty<Il2CppSystem.Object>())} {i}");
playerControl.SetColor((byte) (i % Palette.PlayerColors.Length));
playerControl.SetHat(i % (uint) HatManager.Instance.AllHats.Count, playerControl.Data.ColorId);
playerControl.SetPet(i % (uint) HatManager.Instance.AllPets.Count);
playerControl.SetSkin(i % (uint) HatManager.Instance.AllSkins.Count);
GameData.Instance.RpcSetTasks(playerControl.PlayerId, new byte[0]);
}
}
if (PlayerControl.LocalPlayer)
{
var position = PlayerControl.LocalPlayer.transform.position;
GUILayout.Label($"x: {position.x}", new Il2CppReferenceArray<GUILayoutOption>(0));
GUILayout.Label($"y: {position.y}", new Il2CppReferenceArray<GUILayoutOption>(0));
}
})
{
Enabled = false
};
TestWindow.Enabled = !TestWindow.Enabled;
}
}
private void Update()
{
if (Input.GetKeyDown(KeyCode.F1))
{
TestWindow.Enabled = !TestWindow.Enabled;
}
}
private void OnGUI()
{
TestWindow.OnGUI();
}
private void OnGUI()
{
TestWindow.OnGUI();
}
}
}
+51 -45
View File
@@ -1,70 +1,76 @@
using System.Linq;
using AmongUs.GameOptions;
using HarmonyLib;
using UnhollowerBaseLib;
using Il2CppInterop.Runtime.InteropTypes.Arrays;
using Reactor.Utilities;
using UnityEngine;
namespace Reactor.Debugger
namespace Reactor.Debugger;
internal static class Patches
{
internal static class Patches
[HarmonyPatch(typeof(GameStartManager), nameof(GameStartManager.Update))]
public static class UpdatePatch
{
[HarmonyPatch(typeof(GameStartManager), nameof(GameStartManager.Update))]
public static class UpdatePatch
public static void Prefix(GameStartManager __instance)
{
public static void Prefix(GameStartManager __instance)
{
__instance.MinPlayers = 1;
}
__instance.MinPlayers = 1;
}
}
[HarmonyPatch(typeof(GameStartManager), nameof(GameStartManager.Update))]
public static class CountdownPatch
[HarmonyPatch(typeof(GameStartManager), nameof(GameStartManager.Update))]
public static class CountdownPatch
{
public static void Prefix(GameStartManager __instance)
{
public static void Prefix(GameStartManager __instance)
{
__instance.countDownTimer = 0;
}
__instance.countDownTimer = 0;
}
}
[HarmonyPatch(typeof(StatsManager), nameof(StatsManager.AmBanned), MethodType.Getter)]
public static class AmBannedPatch
[HarmonyPatch(typeof(StatsManager), nameof(StatsManager.AmBanned), MethodType.Getter)]
public static class AmBannedPatch
{
public static void Postfix(out bool __result)
{
public static void Postfix(out bool __result)
{
__result = false;
}
__result = false;
}
}
[HarmonyPatch(typeof(ShipStatus), nameof(ShipStatus.CheckEndCriteria))]
[HarmonyPriority(Priority.First)]
public static class CheckEndCriteriaPatch
[HarmonyPatch]
[HarmonyPriority(Priority.First)]
public static class CheckEndCriteriaPatch
{
[HarmonyPatch(typeof(LogicGameFlow), nameof(LogicGameFlow.CheckEndCriteria))]
[HarmonyPatch(typeof(LogicGameFlowNormal), nameof(LogicGameFlow.CheckEndCriteria))]
[HarmonyPatch(typeof(LogicGameFlowHnS), nameof(LogicGameFlow.CheckEndCriteria))]
public static bool Prefix()
{
public static bool Prefix()
{
return !PluginSingleton<DebuggerPlugin>.Instance.Component.DisableGameEnd;
}
return !PluginSingleton<DebuggerPlugin>.Instance.Component.DisableGameEnd;
}
}
[HarmonyPatch(typeof(GameSettingMenu), nameof(GameSettingMenu.OnEnable))]
public static class GameSettingMenuPatch
[HarmonyPatch(typeof(GameSettingMenu), nameof(GameSettingMenu.Start))]
public static class GameSettingMenuPatch
{
public static void Prefix(GameSettingMenu __instance)
{
public static void Prefix(GameSettingMenu __instance)
{
// Unlocks map/impostor amount changing in online (for testing on your custom servers)
__instance.HideForOnline = new Il2CppReferenceArray<Transform>(0);
}
// Unlocks map/impostor amount changing in online (for testing on your custom servers)
__instance.HideForOnline = new Il2CppReferenceArray<Transform>(0);
}
}
[HarmonyPatch(typeof(GameOptionsMenu), nameof(GameOptionsMenu.Start))]
[HarmonyPriority(Priority.First)]
public static class GameOptionsMenuPatch
[HarmonyPatch(typeof(GameOptionsMenu), nameof(GameOptionsMenu.Start))]
[HarmonyPriority(Priority.First)]
public static class GameOptionsMenuPatch
{
public static void Postfix(GameOptionsMenu __instance)
{
public static void Postfix(GameOptionsMenu __instance)
{
__instance.Children
.Single(o => o.Title == StringNames.GameNumImpostors)
.Cast<NumberOption>()
.ValidRange = new FloatRange(0, byte.MaxValue);
}
if (GameOptionsManager.Instance.CurrentGameOptions.GameMode != GameModes.Normal) return;
__instance.Children
.Single(o => o.Title == StringNames.GameNumImpostors)
.Cast<NumberOption>()
.ValidRange = new FloatRange(0, byte.MaxValue);
}
}
}
+1 -4
View File
@@ -1,15 +1,12 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>netstandard2.1</TargetFramework>
<LangVersion>latest</LangVersion>
<Version>0.1.0</Version>
<Description>Debugging mod for Reactor</Description>
<Authors>NuclearPowered</Authors>
</PropertyGroup>
<ItemGroup>
<ProjectReference Include="..\Reactor\Reactor.csproj" />
<ProjectReference Include="..\Reactor\Reactor.csproj" Private="false" />
</ItemGroup>
<Import Project="../AmongUs.props" />
+875
View File
@@ -0,0 +1,875 @@
{
"version": 1,
"dependencies": {
"net6.0": {
"AmongUs.GameLibs.Steam": {
"type": "Direct",
"requested": "[2022.12.8, )",
"resolved": "2022.12.8",
"contentHash": "IJsIi89xUYRvA54YtNVEJjf25hhF3LWzkNBslKCNDUpL1aQ/PhNyO4j18pO71DCgW/qr1P1j8+CwByuBLsInNA=="
},
"BepInEx.AutoPlugin": {
"type": "Direct",
"requested": "[1.1.0, )",
"resolved": "1.1.0",
"contentHash": "/7Nmc1EA9lYlGBiyz6qPAaHvlcJHEjFZ1RFpGX+8EBj3GrgoX5kbpnZusuSHoOlLx0l+CnzKuQNE54B8UaGPyw=="
},
"BepInEx.IL2CPP.MSBuild": {
"type": "Direct",
"requested": "[2.0.1, )",
"resolved": "2.0.1",
"contentHash": "hUZjCV0t8dkw/Z/zq4Zl405QP7frBk/LVfMdUmUz+7XOhGd7lYPKrR48A5vbGl2QeHudMxlkXzAr9WM3Duq2SQ=="
},
"BepInEx.Unity.IL2CPP": {
"type": "Direct",
"requested": "[6.0.0-be.663, )",
"resolved": "6.0.0-be.663",
"contentHash": "J+mZ4svyTt4ZYbUoPwpVtF5QCGfzC42VuYJ7z1K6Qt8YlBEZx3rnmUmaEnoJIqN5wN7BSnQgzEmrRfdbrgtTnA==",
"dependencies": {
"BepInEx.Core": "6.0.0-be.663",
"BepInEx.Unity.Common": "6.0.0-be.663",
"HarmonyX": "2.10.1",
"Iced": "1.17.0",
"Il2CppInterop.Generator": "1.4.0",
"Il2CppInterop.HarmonySupport": "1.4.0",
"Il2CppInterop.Runtime": "1.4.0",
"MonoMod.RuntimeDetour": "22.5.1.1",
"Samboy063.Cpp2IL.Core": "2022.0.7.2"
}
},
"StyleCop.Analyzers": {
"type": "Direct",
"requested": "[1.2.0-beta.435, )",
"resolved": "1.2.0-beta.435",
"contentHash": "TADk7vdGXtfTnYCV7GyleaaRTQjfoSfZXprQrVMm7cSJtJbFc1QIbWPyLvrgrfGdfHbGmUPvaN4ODKNxg2jgPQ==",
"dependencies": {
"StyleCop.Analyzers.Unstable": "1.2.0.435"
}
},
"AssetRipper.VersionUtilities": {
"type": "Transitive",
"resolved": "1.2.1",
"contentHash": "knQ/W1YwTZS2AbdaZh+nhyyBEZQPQDcahhSOnh88i+cdg4/FEoFJiCwaavgFvCMNuUeHTbcZc4qttF8WQ8xLIA=="
},
"BepInEx.Core": {
"type": "Transitive",
"resolved": "6.0.0-be.663",
"contentHash": "yTlqwieyV3FCzSo4tfiIlS7pTqVtEZwrwHnograkWO4loECeYpShcpoCoxnhQ0vkWsnWGThMK7NodHhjZ+jQDA==",
"dependencies": {
"HarmonyX": "2.10.1",
"MonoMod.Utils": "22.5.1.1",
"SemanticVersioning": "2.0.2"
}
},
"BepInEx.Unity.Common": {
"type": "Transitive",
"resolved": "6.0.0-be.663",
"contentHash": "kxv0yXJQ7YPzUQzlwkpVzmTkdd87kVcQhMjkrwqpowJ0Yx5vEwPUrRyG/pwMH5/cK+2WHCn/2akGWrW0C4vUAQ==",
"dependencies": {
"AssetRipper.VersionUtilities": "1.2.1",
"MonoMod.Utils": "22.5.1.1"
}
},
"HarmonyX": {
"type": "Transitive",
"resolved": "2.10.1",
"contentHash": "9LodMC9Y0u1TW96eKJoWrFJFpmzbgojEO38/Q+e7c1mFPhmHt8xcR8qhI06iF1rf0Dnsk+hqENFVSgbtwl/bEw==",
"dependencies": {
"MonoMod.RuntimeDetour": "22.3.23.4",
"System.Reflection.Emit": "4.7.0"
}
},
"Iced": {
"type": "Transitive",
"resolved": "1.17.0",
"contentHash": "8x+HCVTl/HHTGpscH3vMBhV8sknN/muZFw9s3TsI8SA6+c43cOTCi2+jE4KsU8pNLbJ++iF2ZFcpcXHXtDglnw=="
},
"Il2CppInterop.Common": {
"type": "Transitive",
"resolved": "1.4.0",
"contentHash": "xl60qoa1nImG6qgOQcjSDW46nLQHoRvSWE7QTDQz7XeMsGwOxAbgDtOvJ4gOvoLijTU79gFZYe8H1CM7TcTQ5g==",
"dependencies": {
"Iced": "1.17.0",
"Microsoft.Extensions.Logging.Abstractions": "6.0.1",
"System.Net.Http": "4.3.4"
}
},
"Il2CppInterop.Generator": {
"type": "Transitive",
"resolved": "1.4.0",
"contentHash": "Q4QqkwQroDwwqB17/DRF6hbHQRIuyLksgxVUEDvXZ3T+ogkrZB9h0Ev36alN0f6e7fcZPRkMrpXOAYwZzPiZag==",
"dependencies": {
"Il2CppInterop.Common": "1.4.0",
"Mono.Cecil": "0.11.3"
}
},
"Il2CppInterop.HarmonySupport": {
"type": "Transitive",
"resolved": "1.4.0",
"contentHash": "Uz4w5PbQ3kLXqUrsQxR35f7xMpfnxLiXthVtNaT3fvHXC8B7arjuBZXeCbcozr6dXFJBDa5W0EElBmH0fWoASg==",
"dependencies": {
"HarmonyX": "2.10.0",
"Il2CppInterop.Runtime": "1.4.0"
}
},
"Il2CppInterop.Runtime": {
"type": "Transitive",
"resolved": "1.4.0",
"contentHash": "ScgsFlbJ3gj5f69As/GT8pSO2WlS7cOeS/n3h4gBqJ01Eq/Lm+s3FBrGpEiuIWALOgmtQYimhjWVpxRt7LYtGw==",
"dependencies": {
"Iced": "1.17.0",
"Il2CppInterop.Common": "1.4.0"
}
},
"IndexRange": {
"type": "Transitive",
"resolved": "1.0.0",
"contentHash": "6TgS1JLSUkpmPLfXBPaAgB39ZUix8E4soXWk2XSDcscVe84i1JKzIAtA7jHbRHSkOOrcr6YA0MpLCeq98y9mYQ=="
},
"js6pak.Gee.External.Capstone": {
"type": "Transitive",
"resolved": "2.1.0",
"contentHash": "YYpq7NM50bSSVUDjXyV/eiITk6syXqItPjKBOb3jEWS6RFsk0DNhpWMPW6b3hKDmArARuWDU6S2pVu1IeVrvIA=="
},
"Microsoft.Extensions.Logging.Abstractions": {
"type": "Transitive",
"resolved": "6.0.1",
"contentHash": "dzB2Cgg+JmrouhjkcQGzSFjjvpwlq353i8oBQO2GWNjCXSzhbtBRUf28HSauWe7eib3wYOdb3tItdjRwAdwCSg=="
},
"Microsoft.NETCore.Platforms": {
"type": "Transitive",
"resolved": "1.1.1",
"contentHash": "TMBuzAHpTenGbGgk0SMTwyEkyijY/Eae4ZGsFNYJvAr/LDn1ku3Etp3FPxChmDp5HHF3kzJuoaa08N0xjqAJfQ=="
},
"Microsoft.NETCore.Targets": {
"type": "Transitive",
"resolved": "1.1.0",
"contentHash": "aOZA3BWfz9RXjpzt0sRJJMjAscAUm3Hoa4UWAfceV9UTYxgwZ1lZt5nO2myFf+/jetYQo4uTP7zS8sJY67BBxg=="
},
"Mono.Cecil": {
"type": "Transitive",
"resolved": "0.11.4",
"contentHash": "IC1h5g0NeJGHIUgzM1P82ld57knhP0IcQfrYITDPXlNpMYGUrsG5TxuaWTjaeqDNQMBDNZkB8L0rBnwsY6JHuQ=="
},
"MonoMod.RuntimeDetour": {
"type": "Transitive",
"resolved": "22.5.1.1",
"contentHash": "WG5zLRuAr8KJEnIkKTuIG1OJCrGIT3pjvnAD43E0FDchHf3Dp985MF/8tmIQvAzCZV87JNs6QKeGGqmwDmpXpw==",
"dependencies": {
"Mono.Cecil": "0.11.4",
"MonoMod.Utils": "22.5.1.1",
"System.Collections.NonGeneric": "4.3.0",
"System.ComponentModel.TypeConverter": "4.3.0",
"System.IO.FileSystem.Primitives": "4.3.0",
"System.Reflection.Emit.ILGeneration": "4.7.0",
"System.Reflection.Emit.Lightweight": "4.7.0",
"System.Reflection.TypeExtensions": "4.7.0"
}
},
"MonoMod.Utils": {
"type": "Transitive",
"resolved": "22.5.1.1",
"contentHash": "vBObO1atXxhi2C4AuC53y87Bqeogi9xIrD1Ym3YWr5uxc8Nrm8SrsFeD1i3x04R999+XQ3FdeHrbXScyWYEHqQ==",
"dependencies": {
"Mono.Cecil": "0.11.4",
"System.Collections.NonGeneric": "4.3.0",
"System.ComponentModel.TypeConverter": "4.3.0",
"System.IO.FileSystem.Primitives": "4.3.0",
"System.Reflection.Emit.ILGeneration": "4.7.0",
"System.Reflection.Emit.Lightweight": "4.7.0",
"System.Reflection.TypeExtensions": "4.7.0"
}
},
"runtime.debian.8-x64.runtime.native.System.Security.Cryptography.OpenSsl": {
"type": "Transitive",
"resolved": "4.3.2",
"contentHash": "7VSGO0URRKoMEAq0Sc9cRz8mb6zbyx/BZDEWhgPdzzpmFhkam3fJ1DAGWFXBI4nGlma+uPKpfuMQP5LXRnOH5g=="
},
"runtime.fedora.23-x64.runtime.native.System.Security.Cryptography.OpenSsl": {
"type": "Transitive",
"resolved": "4.3.2",
"contentHash": "0oAaTAm6e2oVH+/Zttt0cuhGaePQYKII1dY8iaqP7CvOpVKgLybKRFvQjXR2LtxXOXTVPNv14j0ot8uV+HrUmw=="
},
"runtime.fedora.24-x64.runtime.native.System.Security.Cryptography.OpenSsl": {
"type": "Transitive",
"resolved": "4.3.2",
"contentHash": "G24ibsCNi5Kbz0oXWynBoRgtGvsw5ZSVEWjv13/KiCAM8C6wz9zzcCniMeQFIkJ2tasjo2kXlvlBZhplL51kGg=="
},
"runtime.native.System": {
"type": "Transitive",
"resolved": "4.3.0",
"contentHash": "c/qWt2LieNZIj1jGnVNsE2Kl23Ya2aSTBuXMD6V7k9KWr6l16Tqdwq+hJScEpWER9753NWC8h96PaVNY5Ld7Jw==",
"dependencies": {
"Microsoft.NETCore.Platforms": "1.1.0",
"Microsoft.NETCore.Targets": "1.1.0"
}
},
"runtime.native.System.Net.Http": {
"type": "Transitive",
"resolved": "4.3.0",
"contentHash": "ZVuZJqnnegJhd2k/PtAbbIcZ3aZeITq3sj06oKfMBSfphW3HDmk/t4ObvbOk/JA/swGR0LNqMksAh/f7gpTROg==",
"dependencies": {
"Microsoft.NETCore.Platforms": "1.1.0",
"Microsoft.NETCore.Targets": "1.1.0"
}
},
"runtime.native.System.Security.Cryptography.Apple": {
"type": "Transitive",
"resolved": "4.3.0",
"contentHash": "DloMk88juo0OuOWr56QG7MNchmafTLYWvABy36izkrLI5VledI0rq28KGs1i9wbpeT9NPQrx/wTf8U2vazqQ3Q==",
"dependencies": {
"runtime.osx.10.10-x64.runtime.native.System.Security.Cryptography.Apple": "4.3.0"
}
},
"runtime.native.System.Security.Cryptography.OpenSsl": {
"type": "Transitive",
"resolved": "4.3.2",
"contentHash": "QR1OwtwehHxSeQvZKXe+iSd+d3XZNkEcuWMFYa2i0aG1l+lR739HPicKMlTbJst3spmeekDVBUS7SeS26s4U/g==",
"dependencies": {
"runtime.debian.8-x64.runtime.native.System.Security.Cryptography.OpenSsl": "4.3.2",
"runtime.fedora.23-x64.runtime.native.System.Security.Cryptography.OpenSsl": "4.3.2",
"runtime.fedora.24-x64.runtime.native.System.Security.Cryptography.OpenSsl": "4.3.2",
"runtime.opensuse.13.2-x64.runtime.native.System.Security.Cryptography.OpenSsl": "4.3.2",
"runtime.opensuse.42.1-x64.runtime.native.System.Security.Cryptography.OpenSsl": "4.3.2",
"runtime.osx.10.10-x64.runtime.native.System.Security.Cryptography.OpenSsl": "4.3.2",
"runtime.rhel.7-x64.runtime.native.System.Security.Cryptography.OpenSsl": "4.3.2",
"runtime.ubuntu.14.04-x64.runtime.native.System.Security.Cryptography.OpenSsl": "4.3.2",
"runtime.ubuntu.16.04-x64.runtime.native.System.Security.Cryptography.OpenSsl": "4.3.2",
"runtime.ubuntu.16.10-x64.runtime.native.System.Security.Cryptography.OpenSsl": "4.3.2"
}
},
"runtime.opensuse.13.2-x64.runtime.native.System.Security.Cryptography.OpenSsl": {
"type": "Transitive",
"resolved": "4.3.2",
"contentHash": "I+GNKGg2xCHueRd1m9PzeEW7WLbNNLznmTuEi8/vZX71HudUbx1UTwlGkiwMri7JLl8hGaIAWnA/GONhu+LOyQ=="
},
"runtime.opensuse.42.1-x64.runtime.native.System.Security.Cryptography.OpenSsl": {
"type": "Transitive",
"resolved": "4.3.2",
"contentHash": "1Z3TAq1ytS1IBRtPXJvEUZdVsfWfeNEhBkbiOCGEl9wwAfsjP2lz3ZFDx5tq8p60/EqbS0HItG5piHuB71RjoA=="
},
"runtime.osx.10.10-x64.runtime.native.System.Security.Cryptography.Apple": {
"type": "Transitive",
"resolved": "4.3.0",
"contentHash": "kVXCuMTrTlxq4XOOMAysuNwsXWpYeboGddNGpIgNSZmv1b6r/s/DPk0fYMB7Q5Qo4bY68o48jt4T4y5BVecbCQ=="
},
"runtime.osx.10.10-x64.runtime.native.System.Security.Cryptography.OpenSsl": {
"type": "Transitive",
"resolved": "4.3.2",
"contentHash": "6mU/cVmmHtQiDXhnzUImxIcDL48GbTk+TsptXyJA+MIOG9LRjPoAQC/qBFB7X+UNyK86bmvGwC8t+M66wsYC8w=="
},
"runtime.rhel.7-x64.runtime.native.System.Security.Cryptography.OpenSsl": {
"type": "Transitive",
"resolved": "4.3.2",
"contentHash": "vjwG0GGcTW/PPg6KVud8F9GLWYuAV1rrw1BKAqY0oh4jcUqg15oYF1+qkGR2x2ZHM4DQnWKQ7cJgYbfncz/lYg=="
},
"runtime.ubuntu.14.04-x64.runtime.native.System.Security.Cryptography.OpenSsl": {
"type": "Transitive",
"resolved": "4.3.2",
"contentHash": "7KMFpTkHC/zoExs+PwP8jDCWcrK9H6L7soowT80CUx3e+nxP/AFnq0AQAW5W76z2WYbLAYCRyPfwYFG6zkvQRw=="
},
"runtime.ubuntu.16.04-x64.runtime.native.System.Security.Cryptography.OpenSsl": {
"type": "Transitive",
"resolved": "4.3.2",
"contentHash": "xrlmRCnKZJLHxyyLIqkZjNXqgxnKdZxfItrPkjI+6pkRo5lHX8YvSZlWrSI5AVwLMi4HbNWP7064hcAWeZKp5w=="
},
"runtime.ubuntu.16.10-x64.runtime.native.System.Security.Cryptography.OpenSsl": {
"type": "Transitive",
"resolved": "4.3.2",
"contentHash": "leXiwfiIkW7Gmn7cgnNcdtNAU70SjmKW3jxGj1iKHOvdn0zRWsgv/l2OJUO5zdGdiv2VRFnAsxxhDgMzofPdWg=="
},
"Samboy063.Cpp2IL.Core": {
"type": "Transitive",
"resolved": "2022.0.7.2",
"contentHash": "e17CAhKSxdAp7vFcYEVxjSc7t7rcvVGBipGhgE9tAjRXY85wZXLlHEVO0AEvMRkLmf9U+if4wK/nZEC1AX6VqQ==",
"dependencies": {
"HarmonyX": "2.5.5",
"Iced": "1.11.1",
"IndexRange": "1.0.0",
"Mono.Cecil": "0.11.4",
"Samboy063.LibCpp2IL": "2022.0.7.2",
"System.Runtime.InteropServices": "4.3.0",
"System.ValueTuple": "4.5.0",
"js6pak.Gee.External.Capstone": "2.1.0"
}
},
"Samboy063.LibCpp2IL": {
"type": "Transitive",
"resolved": "2022.0.7.2",
"contentHash": "DpVeU0dQkUJCpbw0f1xKOG8vimdK2oYhrVABC7HDE3/ikGjhnMZd3i5b1joKDHZ+AiL90TWOaEXPcy24rCZ0dA==",
"dependencies": {
"IndexRange": "1.0.0",
"Samboy063.WasmDisassembler": "2022.0.2"
}
},
"Samboy063.WasmDisassembler": {
"type": "Transitive",
"resolved": "2022.0.2",
"contentHash": "2uu+xBb7M3HKfBx9tAY6jiDieAf0hRnQjSmGX+7IdE6i24dYsx6TYgtrLvRx5lOuF2M8DijZ5H8yQ1pcuCs2SA=="
},
"SemanticVersioning": {
"type": "Transitive",
"resolved": "2.0.2",
"contentHash": "4EQgYdNZ92SyaO7YFk6olVnebF5V+jrHyMUjvPq89tLeMo8NSfgDF+6Zwq/lgh9j/0yfQp9Lkm0ZA0rUATCZFA=="
},
"StyleCop.Analyzers.Unstable": {
"type": "Transitive",
"resolved": "1.2.0.435",
"contentHash": "ouwPWZxbOV3SmCZxIRqHvljkSzkCyi1tDoMzQtDb/bRP8ctASV/iRJr+A2Gdj0QLaLmWnqTWDrH82/iP+X80Lg=="
},
"System.Collections": {
"type": "Transitive",
"resolved": "4.3.0",
"contentHash": "3Dcj85/TBdVpL5Zr+gEEBUuFe2icOnLalmEh9hfck1PTYbbyWuZgh4fmm2ysCLTrqLQw6t3TgTyJ+VLp+Qb+Lw==",
"dependencies": {
"Microsoft.NETCore.Platforms": "1.1.0",
"Microsoft.NETCore.Targets": "1.1.0",
"System.Runtime": "4.3.0"
}
},
"System.Collections.Concurrent": {
"type": "Transitive",
"resolved": "4.3.0",
"contentHash": "ztl69Xp0Y/UXCL+3v3tEU+lIy+bvjKNUmopn1wep/a291pVPK7dxBd6T7WnlQqRog+d1a/hSsgRsmFnIBKTPLQ==",
"dependencies": {
"System.Collections": "4.3.0",
"System.Diagnostics.Debug": "4.3.0",
"System.Diagnostics.Tracing": "4.3.0",
"System.Globalization": "4.3.0",
"System.Reflection": "4.3.0",
"System.Resources.ResourceManager": "4.3.0",
"System.Runtime": "4.3.0",
"System.Runtime.Extensions": "4.3.0",
"System.Threading": "4.3.0",
"System.Threading.Tasks": "4.3.0"
}
},
"System.Collections.NonGeneric": {
"type": "Transitive",
"resolved": "4.3.0",
"contentHash": "prtjIEMhGUnQq6RnPEYLpFt8AtLbp9yq2zxOSrY7KJJZrw25Fi97IzBqY7iqssbM61Ek5b8f3MG/sG1N2sN5KA==",
"dependencies": {
"System.Diagnostics.Debug": "4.3.0",
"System.Globalization": "4.3.0",
"System.Resources.ResourceManager": "4.3.0",
"System.Runtime": "4.3.0",
"System.Runtime.Extensions": "4.3.0",
"System.Threading": "4.3.0"
}
},
"System.Collections.Specialized": {
"type": "Transitive",
"resolved": "4.3.0",
"contentHash": "Epx8PoVZR0iuOnJJDzp7pWvdfMMOAvpUo95pC4ScH2mJuXkKA2Y4aR3cG9qt2klHgSons1WFh4kcGW7cSXvrxg==",
"dependencies": {
"System.Collections.NonGeneric": "4.3.0",
"System.Globalization": "4.3.0",
"System.Globalization.Extensions": "4.3.0",
"System.Resources.ResourceManager": "4.3.0",
"System.Runtime": "4.3.0",
"System.Runtime.Extensions": "4.3.0",
"System.Threading": "4.3.0"
}
},
"System.ComponentModel": {
"type": "Transitive",
"resolved": "4.3.0",
"contentHash": "VyGn1jGRZVfxnh8EdvDCi71v3bMXrsu8aYJOwoV7SNDLVhiEqwP86pPMyRGsDsxhXAm2b3o9OIqeETfN5qfezw==",
"dependencies": {
"System.Runtime": "4.3.0"
}
},
"System.ComponentModel.Primitives": {
"type": "Transitive",
"resolved": "4.3.0",
"contentHash": "j8GUkCpM8V4d4vhLIIoBLGey2Z5bCkMVNjEZseyAlm4n5arcsJOeI3zkUP+zvZgzsbLTYh4lYeP/ZD/gdIAPrw==",
"dependencies": {
"System.ComponentModel": "4.3.0",
"System.Resources.ResourceManager": "4.3.0",
"System.Runtime": "4.3.0"
}
},
"System.ComponentModel.TypeConverter": {
"type": "Transitive",
"resolved": "4.3.0",
"contentHash": "16pQ6P+EdhcXzPiEK4kbA953Fu0MNG2ovxTZU81/qsCd1zPRsKc3uif5NgvllCY598k6bI0KUyKW8fanlfaDQg==",
"dependencies": {
"System.Collections": "4.3.0",
"System.Collections.NonGeneric": "4.3.0",
"System.Collections.Specialized": "4.3.0",
"System.ComponentModel": "4.3.0",
"System.ComponentModel.Primitives": "4.3.0",
"System.Globalization": "4.3.0",
"System.Linq": "4.3.0",
"System.Reflection": "4.3.0",
"System.Reflection.Extensions": "4.3.0",
"System.Reflection.Primitives": "4.3.0",
"System.Reflection.TypeExtensions": "4.3.0",
"System.Resources.ResourceManager": "4.3.0",
"System.Runtime": "4.3.0",
"System.Runtime.Extensions": "4.3.0",
"System.Threading": "4.3.0"
}
},
"System.Diagnostics.Debug": {
"type": "Transitive",
"resolved": "4.3.0",
"contentHash": "ZUhUOdqmaG5Jk3Xdb8xi5kIyQYAA4PnTNlHx1mu9ZY3qv4ELIdKbnL/akbGaKi2RnNUWaZsAs31rvzFdewTj2g==",
"dependencies": {
"Microsoft.NETCore.Platforms": "1.1.0",
"Microsoft.NETCore.Targets": "1.1.0",
"System.Runtime": "4.3.0"
}
},
"System.Diagnostics.DiagnosticSource": {
"type": "Transitive",
"resolved": "4.3.0",
"contentHash": "tD6kosZnTAGdrEa0tZSuFyunMbt/5KYDnHdndJYGqZoNy00XVXyACd5d6KnE1YgYv3ne2CjtAfNXo/fwEhnKUA==",
"dependencies": {
"System.Collections": "4.3.0",
"System.Diagnostics.Tracing": "4.3.0",
"System.Reflection": "4.3.0",
"System.Runtime": "4.3.0",
"System.Threading": "4.3.0"
}
},
"System.Diagnostics.Tracing": {
"type": "Transitive",
"resolved": "4.3.0",
"contentHash": "rswfv0f/Cqkh78rA5S8eN8Neocz234+emGCtTF3lxPY96F+mmmUen6tbn0glN6PMvlKQb9bPAY5e9u7fgPTkKw==",
"dependencies": {
"Microsoft.NETCore.Platforms": "1.1.0",
"Microsoft.NETCore.Targets": "1.1.0",
"System.Runtime": "4.3.0"
}
},
"System.Globalization": {
"type": "Transitive",
"resolved": "4.3.0",
"contentHash": "kYdVd2f2PAdFGblzFswE4hkNANJBKRmsfa2X5LG2AcWE1c7/4t0pYae1L8vfZ5xvE2nK/R9JprtToA61OSHWIg==",
"dependencies": {
"Microsoft.NETCore.Platforms": "1.1.0",
"Microsoft.NETCore.Targets": "1.1.0",
"System.Runtime": "4.3.0"
}
},
"System.Globalization.Calendars": {
"type": "Transitive",
"resolved": "4.3.0",
"contentHash": "GUlBtdOWT4LTV3I+9/PJW+56AnnChTaOqqTLFtdmype/L500M2LIyXgmtd9X2P2VOkmJd5c67H5SaC2QcL1bFA==",
"dependencies": {
"Microsoft.NETCore.Platforms": "1.1.0",
"Microsoft.NETCore.Targets": "1.1.0",
"System.Globalization": "4.3.0",
"System.Runtime": "4.3.0"
}
},
"System.Globalization.Extensions": {
"type": "Transitive",
"resolved": "4.3.0",
"contentHash": "FhKmdR6MPG+pxow6wGtNAWdZh7noIOpdD5TwQ3CprzgIE1bBBoim0vbR1+AWsWjQmU7zXHgQo4TWSP6lCeiWcQ==",
"dependencies": {
"Microsoft.NETCore.Platforms": "1.1.0",
"System.Globalization": "4.3.0",
"System.Resources.ResourceManager": "4.3.0",
"System.Runtime": "4.3.0",
"System.Runtime.Extensions": "4.3.0",
"System.Runtime.InteropServices": "4.3.0"
}
},
"System.IO": {
"type": "Transitive",
"resolved": "4.3.0",
"contentHash": "3qjaHvxQPDpSOYICjUoTsmoq5u6QJAFRUITgeT/4gqkF1bajbSmb1kwSxEA8AHlofqgcKJcM8udgieRNhaJ5Cg==",
"dependencies": {
"Microsoft.NETCore.Platforms": "1.1.0",
"Microsoft.NETCore.Targets": "1.1.0",
"System.Runtime": "4.3.0",
"System.Text.Encoding": "4.3.0",
"System.Threading.Tasks": "4.3.0"
}
},
"System.IO.FileSystem": {
"type": "Transitive",
"resolved": "4.3.0",
"contentHash": "3wEMARTnuio+ulnvi+hkRNROYwa1kylvYahhcLk4HSoVdl+xxTFVeVlYOfLwrDPImGls0mDqbMhrza8qnWPTdA==",
"dependencies": {
"Microsoft.NETCore.Platforms": "1.1.0",
"Microsoft.NETCore.Targets": "1.1.0",
"System.IO": "4.3.0",
"System.IO.FileSystem.Primitives": "4.3.0",
"System.Runtime": "4.3.0",
"System.Runtime.Handles": "4.3.0",
"System.Text.Encoding": "4.3.0",
"System.Threading.Tasks": "4.3.0"
}
},
"System.IO.FileSystem.Primitives": {
"type": "Transitive",
"resolved": "4.3.0",
"contentHash": "6QOb2XFLch7bEc4lIcJH49nJN2HV+OC3fHDgsLVsBVBk3Y4hFAnOBGzJ2lUu7CyDDFo9IBWkSsnbkT6IBwwiMw==",
"dependencies": {
"System.Runtime": "4.3.0"
}
},
"System.Linq": {
"type": "Transitive",
"resolved": "4.3.0",
"contentHash": "5DbqIUpsDp0dFftytzuMmc0oeMdQwjcP/EWxsksIz/w1TcFRkZ3yKKz0PqiYFMmEwPSWw+qNVqD7PJ889JzHbw==",
"dependencies": {
"System.Collections": "4.3.0",
"System.Diagnostics.Debug": "4.3.0",
"System.Resources.ResourceManager": "4.3.0",
"System.Runtime": "4.3.0",
"System.Runtime.Extensions": "4.3.0"
}
},
"System.Net.Http": {
"type": "Transitive",
"resolved": "4.3.4",
"contentHash": "aOa2d51SEbmM+H+Csw7yJOuNZoHkrP2XnAurye5HWYgGVVU54YZDvsLUYRv6h18X3sPnjNCANmN7ZhIPiqMcjA==",
"dependencies": {
"Microsoft.NETCore.Platforms": "1.1.1",
"System.Collections": "4.3.0",
"System.Diagnostics.Debug": "4.3.0",
"System.Diagnostics.DiagnosticSource": "4.3.0",
"System.Diagnostics.Tracing": "4.3.0",
"System.Globalization": "4.3.0",
"System.Globalization.Extensions": "4.3.0",
"System.IO": "4.3.0",
"System.IO.FileSystem": "4.3.0",
"System.Net.Primitives": "4.3.0",
"System.Resources.ResourceManager": "4.3.0",
"System.Runtime": "4.3.0",
"System.Runtime.Extensions": "4.3.0",
"System.Runtime.Handles": "4.3.0",
"System.Runtime.InteropServices": "4.3.0",
"System.Security.Cryptography.Algorithms": "4.3.0",
"System.Security.Cryptography.Encoding": "4.3.0",
"System.Security.Cryptography.OpenSsl": "4.3.0",
"System.Security.Cryptography.Primitives": "4.3.0",
"System.Security.Cryptography.X509Certificates": "4.3.0",
"System.Text.Encoding": "4.3.0",
"System.Threading": "4.3.0",
"System.Threading.Tasks": "4.3.0",
"runtime.native.System": "4.3.0",
"runtime.native.System.Net.Http": "4.3.0",
"runtime.native.System.Security.Cryptography.OpenSsl": "4.3.2"
}
},
"System.Net.Primitives": {
"type": "Transitive",
"resolved": "4.3.0",
"contentHash": "qOu+hDwFwoZPbzPvwut2qATe3ygjeQBDQj91xlsaqGFQUI5i4ZnZb8yyQuLGpDGivEPIt8EJkd1BVzVoP31FXA==",
"dependencies": {
"Microsoft.NETCore.Platforms": "1.1.0",
"Microsoft.NETCore.Targets": "1.1.0",
"System.Runtime": "4.3.0",
"System.Runtime.Handles": "4.3.0"
}
},
"System.Reflection": {
"type": "Transitive",
"resolved": "4.3.0",
"contentHash": "KMiAFoW7MfJGa9nDFNcfu+FpEdiHpWgTcS2HdMpDvt9saK3y/G4GwprPyzqjFH9NTaGPQeWNHU+iDlDILj96aQ==",
"dependencies": {
"Microsoft.NETCore.Platforms": "1.1.0",
"Microsoft.NETCore.Targets": "1.1.0",
"System.IO": "4.3.0",
"System.Reflection.Primitives": "4.3.0",
"System.Runtime": "4.3.0"
}
},
"System.Reflection.Emit": {
"type": "Transitive",
"resolved": "4.7.0",
"contentHash": "VR4kk8XLKebQ4MZuKuIni/7oh+QGFmZW3qORd1GvBq/8026OpW501SzT/oypwiQl4TvT8ErnReh/NzY9u+C6wQ=="
},
"System.Reflection.Emit.ILGeneration": {
"type": "Transitive",
"resolved": "4.7.0",
"contentHash": "AucBYo3DSI0IDxdUjKksBcQJXPHyoPyrCXYURW1WDsLI4M65Ar/goSHjdnHOAY9MiYDNKqDlIgaYm+zL2hA1KA=="
},
"System.Reflection.Emit.Lightweight": {
"type": "Transitive",
"resolved": "4.7.0",
"contentHash": "a4OLB4IITxAXJeV74MDx49Oq2+PsF6Sml54XAFv+2RyWwtDBcabzoxiiJRhdhx+gaohLh4hEGCLQyBozXoQPqA=="
},
"System.Reflection.Extensions": {
"type": "Transitive",
"resolved": "4.3.0",
"contentHash": "rJkrJD3kBI5B712aRu4DpSIiHRtr6QlfZSQsb0hYHrDCZORXCFjQfoipo2LaMUHoT9i1B7j7MnfaEKWDFmFQNQ==",
"dependencies": {
"Microsoft.NETCore.Platforms": "1.1.0",
"Microsoft.NETCore.Targets": "1.1.0",
"System.Reflection": "4.3.0",
"System.Runtime": "4.3.0"
}
},
"System.Reflection.Primitives": {
"type": "Transitive",
"resolved": "4.3.0",
"contentHash": "5RXItQz5As4xN2/YUDxdpsEkMhvw3e6aNveFXUn4Hl/udNTCNhnKp8lT9fnc3MhvGKh1baak5CovpuQUXHAlIA==",
"dependencies": {
"Microsoft.NETCore.Platforms": "1.1.0",
"Microsoft.NETCore.Targets": "1.1.0",
"System.Runtime": "4.3.0"
}
},
"System.Reflection.TypeExtensions": {
"type": "Transitive",
"resolved": "4.7.0",
"contentHash": "VybpaOQQhqE6siHppMktjfGBw1GCwvCqiufqmP8F1nj7fTUNtW35LOEt3UZTEsECfo+ELAl/9o9nJx3U91i7vA=="
},
"System.Resources.ResourceManager": {
"type": "Transitive",
"resolved": "4.3.0",
"contentHash": "/zrcPkkWdZmI4F92gL/TPumP98AVDu/Wxr3CSJGQQ+XN6wbRZcyfSKVoPo17ilb3iOr0cCRqJInGwNMolqhS8A==",
"dependencies": {
"Microsoft.NETCore.Platforms": "1.1.0",
"Microsoft.NETCore.Targets": "1.1.0",
"System.Globalization": "4.3.0",
"System.Reflection": "4.3.0",
"System.Runtime": "4.3.0"
}
},
"System.Runtime": {
"type": "Transitive",
"resolved": "4.3.0",
"contentHash": "JufQi0vPQ0xGnAczR13AUFglDyVYt4Kqnz1AZaiKZ5+GICq0/1MH/mO/eAJHt/mHW1zjKBJd7kV26SrxddAhiw==",
"dependencies": {
"Microsoft.NETCore.Platforms": "1.1.0",
"Microsoft.NETCore.Targets": "1.1.0"
}
},
"System.Runtime.Extensions": {
"type": "Transitive",
"resolved": "4.3.0",
"contentHash": "guW0uK0fn5fcJJ1tJVXYd7/1h5F+pea1r7FLSOz/f8vPEqbR2ZAknuRDvTQ8PzAilDveOxNjSfr0CHfIQfFk8g==",
"dependencies": {
"Microsoft.NETCore.Platforms": "1.1.0",
"Microsoft.NETCore.Targets": "1.1.0",
"System.Runtime": "4.3.0"
}
},
"System.Runtime.Handles": {
"type": "Transitive",
"resolved": "4.3.0",
"contentHash": "OKiSUN7DmTWeYb3l51A7EYaeNMnvxwE249YtZz7yooT4gOZhmTjIn48KgSsw2k2lYdLgTKNJw/ZIfSElwDRVgg==",
"dependencies": {
"Microsoft.NETCore.Platforms": "1.1.0",
"Microsoft.NETCore.Targets": "1.1.0",
"System.Runtime": "4.3.0"
}
},
"System.Runtime.InteropServices": {
"type": "Transitive",
"resolved": "4.3.0",
"contentHash": "uv1ynXqiMK8mp1GM3jDqPCFN66eJ5w5XNomaK2XD+TuCroNTLFGeZ+WCmBMcBDyTFKou3P6cR6J/QsaqDp7fGQ==",
"dependencies": {
"Microsoft.NETCore.Platforms": "1.1.0",
"Microsoft.NETCore.Targets": "1.1.0",
"System.Reflection": "4.3.0",
"System.Reflection.Primitives": "4.3.0",
"System.Runtime": "4.3.0",
"System.Runtime.Handles": "4.3.0"
}
},
"System.Runtime.Numerics": {
"type": "Transitive",
"resolved": "4.3.0",
"contentHash": "yMH+MfdzHjy17l2KESnPiF2dwq7T+xLnSJar7slyimAkUh/gTrS9/UQOtv7xarskJ2/XDSNvfLGOBQPjL7PaHQ==",
"dependencies": {
"System.Globalization": "4.3.0",
"System.Resources.ResourceManager": "4.3.0",
"System.Runtime": "4.3.0",
"System.Runtime.Extensions": "4.3.0"
}
},
"System.Security.Cryptography.Algorithms": {
"type": "Transitive",
"resolved": "4.3.0",
"contentHash": "W1kd2Y8mYSCgc3ULTAZ0hOP2dSdG5YauTb1089T0/kRcN2MpSAW1izOFROrJgxSlMn3ArsgHXagigyi+ibhevg==",
"dependencies": {
"Microsoft.NETCore.Platforms": "1.1.0",
"System.Collections": "4.3.0",
"System.IO": "4.3.0",
"System.Resources.ResourceManager": "4.3.0",
"System.Runtime": "4.3.0",
"System.Runtime.Extensions": "4.3.0",
"System.Runtime.Handles": "4.3.0",
"System.Runtime.InteropServices": "4.3.0",
"System.Runtime.Numerics": "4.3.0",
"System.Security.Cryptography.Encoding": "4.3.0",
"System.Security.Cryptography.Primitives": "4.3.0",
"System.Text.Encoding": "4.3.0",
"runtime.native.System.Security.Cryptography.Apple": "4.3.0",
"runtime.native.System.Security.Cryptography.OpenSsl": "4.3.0"
}
},
"System.Security.Cryptography.Cng": {
"type": "Transitive",
"resolved": "4.3.0",
"contentHash": "03idZOqFlsKRL4W+LuCpJ6dBYDUWReug6lZjBa3uJWnk5sPCUXckocevTaUA8iT/MFSrY/2HXkOt753xQ/cf8g==",
"dependencies": {
"Microsoft.NETCore.Platforms": "1.1.0",
"System.IO": "4.3.0",
"System.Resources.ResourceManager": "4.3.0",
"System.Runtime": "4.3.0",
"System.Runtime.Extensions": "4.3.0",
"System.Runtime.Handles": "4.3.0",
"System.Runtime.InteropServices": "4.3.0",
"System.Security.Cryptography.Algorithms": "4.3.0",
"System.Security.Cryptography.Encoding": "4.3.0",
"System.Security.Cryptography.Primitives": "4.3.0",
"System.Text.Encoding": "4.3.0"
}
},
"System.Security.Cryptography.Csp": {
"type": "Transitive",
"resolved": "4.3.0",
"contentHash": "X4s/FCkEUnRGnwR3aSfVIkldBmtURMhmexALNTwpjklzxWU7yjMk7GHLKOZTNkgnWnE0q7+BCf9N2LVRWxewaA==",
"dependencies": {
"Microsoft.NETCore.Platforms": "1.1.0",
"System.IO": "4.3.0",
"System.Reflection": "4.3.0",
"System.Resources.ResourceManager": "4.3.0",
"System.Runtime": "4.3.0",
"System.Runtime.Extensions": "4.3.0",
"System.Runtime.Handles": "4.3.0",
"System.Runtime.InteropServices": "4.3.0",
"System.Security.Cryptography.Algorithms": "4.3.0",
"System.Security.Cryptography.Encoding": "4.3.0",
"System.Security.Cryptography.Primitives": "4.3.0",
"System.Text.Encoding": "4.3.0",
"System.Threading": "4.3.0"
}
},
"System.Security.Cryptography.Encoding": {
"type": "Transitive",
"resolved": "4.3.0",
"contentHash": "1DEWjZZly9ae9C79vFwqaO5kaOlI5q+3/55ohmq/7dpDyDfc8lYe7YVxJUZ5MF/NtbkRjwFRo14yM4OEo9EmDw==",
"dependencies": {
"Microsoft.NETCore.Platforms": "1.1.0",
"System.Collections": "4.3.0",
"System.Collections.Concurrent": "4.3.0",
"System.Linq": "4.3.0",
"System.Resources.ResourceManager": "4.3.0",
"System.Runtime": "4.3.0",
"System.Runtime.Extensions": "4.3.0",
"System.Runtime.Handles": "4.3.0",
"System.Runtime.InteropServices": "4.3.0",
"System.Security.Cryptography.Primitives": "4.3.0",
"System.Text.Encoding": "4.3.0",
"runtime.native.System.Security.Cryptography.OpenSsl": "4.3.0"
}
},
"System.Security.Cryptography.OpenSsl": {
"type": "Transitive",
"resolved": "4.3.0",
"contentHash": "h4CEgOgv5PKVF/HwaHzJRiVboL2THYCou97zpmhjghx5frc7fIvlkY1jL+lnIQyChrJDMNEXS6r7byGif8Cy4w==",
"dependencies": {
"System.Collections": "4.3.0",
"System.IO": "4.3.0",
"System.Resources.ResourceManager": "4.3.0",
"System.Runtime": "4.3.0",
"System.Runtime.Extensions": "4.3.0",
"System.Runtime.Handles": "4.3.0",
"System.Runtime.InteropServices": "4.3.0",
"System.Runtime.Numerics": "4.3.0",
"System.Security.Cryptography.Algorithms": "4.3.0",
"System.Security.Cryptography.Encoding": "4.3.0",
"System.Security.Cryptography.Primitives": "4.3.0",
"System.Text.Encoding": "4.3.0",
"runtime.native.System.Security.Cryptography.OpenSsl": "4.3.0"
}
},
"System.Security.Cryptography.Primitives": {
"type": "Transitive",
"resolved": "4.3.0",
"contentHash": "7bDIyVFNL/xKeFHjhobUAQqSpJq9YTOpbEs6mR233Et01STBMXNAc/V+BM6dwYGc95gVh/Zf+iVXWzj3mE8DWg==",
"dependencies": {
"System.Diagnostics.Debug": "4.3.0",
"System.Globalization": "4.3.0",
"System.IO": "4.3.0",
"System.Resources.ResourceManager": "4.3.0",
"System.Runtime": "4.3.0",
"System.Threading": "4.3.0",
"System.Threading.Tasks": "4.3.0"
}
},
"System.Security.Cryptography.X509Certificates": {
"type": "Transitive",
"resolved": "4.3.0",
"contentHash": "t2Tmu6Y2NtJ2um0RtcuhP7ZdNNxXEgUm2JeoA/0NvlMjAhKCnM1NX07TDl3244mVp3QU6LPEhT3HTtH1uF7IYw==",
"dependencies": {
"Microsoft.NETCore.Platforms": "1.1.0",
"System.Collections": "4.3.0",
"System.Diagnostics.Debug": "4.3.0",
"System.Globalization": "4.3.0",
"System.Globalization.Calendars": "4.3.0",
"System.IO": "4.3.0",
"System.IO.FileSystem": "4.3.0",
"System.IO.FileSystem.Primitives": "4.3.0",
"System.Resources.ResourceManager": "4.3.0",
"System.Runtime": "4.3.0",
"System.Runtime.Extensions": "4.3.0",
"System.Runtime.Handles": "4.3.0",
"System.Runtime.InteropServices": "4.3.0",
"System.Runtime.Numerics": "4.3.0",
"System.Security.Cryptography.Algorithms": "4.3.0",
"System.Security.Cryptography.Cng": "4.3.0",
"System.Security.Cryptography.Csp": "4.3.0",
"System.Security.Cryptography.Encoding": "4.3.0",
"System.Security.Cryptography.OpenSsl": "4.3.0",
"System.Security.Cryptography.Primitives": "4.3.0",
"System.Text.Encoding": "4.3.0",
"System.Threading": "4.3.0",
"runtime.native.System": "4.3.0",
"runtime.native.System.Net.Http": "4.3.0",
"runtime.native.System.Security.Cryptography.OpenSsl": "4.3.0"
}
},
"System.Text.Encoding": {
"type": "Transitive",
"resolved": "4.3.0",
"contentHash": "BiIg+KWaSDOITze6jGQynxg64naAPtqGHBwDrLaCtixsa5bKiR8dpPOHA7ge3C0JJQizJE+sfkz1wV+BAKAYZw==",
"dependencies": {
"Microsoft.NETCore.Platforms": "1.1.0",
"Microsoft.NETCore.Targets": "1.1.0",
"System.Runtime": "4.3.0"
}
},
"System.Threading": {
"type": "Transitive",
"resolved": "4.3.0",
"contentHash": "VkUS0kOBcUf3Wwm0TSbrevDDZ6BlM+b/HRiapRFWjM5O0NS0LviG0glKmFK+hhPDd1XFeSdU1GmlLhb2CoVpIw==",
"dependencies": {
"System.Runtime": "4.3.0",
"System.Threading.Tasks": "4.3.0"
}
},
"System.Threading.Tasks": {
"type": "Transitive",
"resolved": "4.3.0",
"contentHash": "LbSxKEdOUhVe8BezB/9uOGGppt+nZf6e1VFyw6v3DN6lqitm0OSn2uXMOdtP0M3W4iMcqcivm2J6UgqiwwnXiA==",
"dependencies": {
"Microsoft.NETCore.Platforms": "1.1.0",
"Microsoft.NETCore.Targets": "1.1.0",
"System.Runtime": "4.3.0"
}
},
"System.ValueTuple": {
"type": "Transitive",
"resolved": "4.5.0",
"contentHash": "okurQJO6NRE/apDIP23ajJ0hpiNmJ+f0BwOlB/cSqTLQlw5upkf+5+96+iG2Jw40G1fCVCyPz/FhIABUjMR+RQ=="
},
"reactor": {
"type": "Project",
"dependencies": {
"BepInEx.Unity.IL2CPP": "[6.0.0-be.663, )"
}
}
}
}
}
+5 -5
View File
@@ -1,7 +1,7 @@
namespace Reactor.Example
namespace Reactor.Example;
public enum CustomRpcCalls : uint
{
public enum CustomRpcCalls : uint
{
Example
}
Example,
MethodRpcExample,
}
@@ -0,0 +1,26 @@
using Reactor.Localization;
namespace Reactor.Example;
public class ExampleLocalizationProvider : LocalizationProvider
{
public override bool TryGetText(StringNames stringName, out string? result)
{
if (stringName == (StringNames) 1337)
{
switch (CurrentLanguage)
{
case SupportedLangs.English:
result = "Cringe English";
return true;
default:
result = "Based " + CurrentLanguage;
return true;
}
}
result = null;
return false;
}
}
+82 -31
View File
@@ -1,49 +1,100 @@
using System;
using System;
using BepInEx;
using BepInEx.IL2CPP;
using Reactor.Extensions;
using BepInEx.Unity.IL2CPP;
using Il2CppInterop.Runtime.Attributes;
using Reactor.Localization;
using Reactor.Localization.Utilities;
using Reactor.Networking;
using UnhollowerBaseLib.Attributes;
using Reactor.Networking.Attributes;
using Reactor.Networking.Rpc;
using Reactor.Utilities;
using Reactor.Utilities.Attributes;
using Reactor.Utilities.ImGui;
using UnityEngine;
using Random = UnityEngine.Random;
namespace Reactor.Example
namespace Reactor.Example;
[BepInAutoPlugin("gg.reactor.Example")]
[BepInProcess("Among Us.exe")]
[BepInDependency(ReactorPlugin.Id)]
[ReactorModFlags(ModFlags.RequireOnAllClients)]
public partial class ExamplePlugin : BasePlugin
{
[BepInPlugin(Id)]
[BepInProcess("Among Us.exe")]
[BepInDependency(ReactorPlugin.Id)]
public class ExamplePlugin : BasePlugin
private static StringNames _helloStringName;
public override void Load()
{
public const string Id = "gg.reactor.Example";
this.AddComponent<ExampleComponent>();
public override void Load()
_helloStringName = CustomStringName.CreateAndRegister("Hello!");
LocalizationManager.Register(new ExampleLocalizationProvider());
}
[RegisterInIl2Cpp]
public class ExampleComponent : MonoBehaviour
{
[HideFromIl2Cpp]
public DragWindow TestWindow { get; }
public ExampleComponent(IntPtr ptr) : base(ptr)
{
var gameObject = new GameObject(nameof(ReactorPlugin)).DontDestroy();
gameObject.AddComponent<ExampleComponent>().Plugin = this;
}
[RegisterInIl2Cpp]
public class ExampleComponent : MonoBehaviour
{
[HideFromIl2Cpp]
public ExamplePlugin Plugin { get; internal set; }
public ExampleComponent(IntPtr ptr) : base(ptr)
TestWindow = new DragWindow(new Rect(60, 20, 0, 0), "Example", () =>
{
}
private void Update()
{
if (Input.GetKeyDown(KeyCode.F3) && AmongUsClient.Instance && PlayerControl.LocalPlayer)
if (GUILayout.Button("Log CustomStringName"))
{
var name = PlayerControl.LocalPlayer.Data.PlayerName;
Rpc<ExampleRpc>.Instance.Send(new ExampleRpc.Data($"Send: from {name}"));
Logger<ExamplePlugin>.Info(TranslationController.Instance.GetString(_helloStringName));
}
if (!AmongUsClient.Instance.AmHost)
if (GUILayout.Button("Log localized string"))
{
Logger<ExamplePlugin>.Info(TranslationController.Instance.GetString((StringNames) 1337));
}
if (AmongUsClient.Instance && PlayerControl.LocalPlayer)
{
if (GUILayout.Button("Send ExampleRpc"))
{
Rpc<ExampleRpc>.Instance.SendTo(AmongUsClient.Instance.HostId, new ExampleRpc.Data($"SendTo: from {name} to host"));
var playerName = PlayerControl.LocalPlayer.Data.PlayerName;
Rpc<ExampleRpc>.Instance.Send(new ExampleRpc.Data($"Send: from {playerName}"), ackCallback: () =>
{
Logger<ExamplePlugin>.Info("Got an acknowledgement for example rpc");
});
if (!AmongUsClient.Instance.AmHost)
{
Rpc<ExampleRpc>.Instance.SendTo(AmongUsClient.Instance.HostId, new ExampleRpc.Data($"SendTo: from {playerName} to host"));
}
}
if (GUILayout.Button("Send MethodExampleRpc"))
{
RpcSay(PlayerControl.LocalPlayer, "Hello from method rpc", Random.value, PlayerControl.LocalPlayer);
}
}
})
{
Enabled = false,
};
}
private void Update()
{
if (Input.GetKeyDown(KeyCode.F2))
{
TestWindow.Enabled = !TestWindow.Enabled;
}
}
private void OnGUI()
{
TestWindow.OnGUI();
}
}
[MethodRpc((uint) CustomRpcCalls.MethodRpcExample)]
public static void RpcSay(PlayerControl player, string text, float number, PlayerControl testPlayer)
{
Logger<ExamplePlugin>.Info($"{player.Data.PlayerName} text: {text} number: {number} testPlayer: {testPlayer.NetId}");
}
}
+21 -29
View File
@@ -1,40 +1,32 @@
using Hazel;
using Reactor.Networking;
using Reactor.Networking.Attributes;
using Reactor.Networking.Rpc;
namespace Reactor.Example
namespace Reactor.Example;
[RegisterCustomRpc((uint) CustomRpcCalls.Example)]
public class ExampleRpc : PlayerCustomRpc<ExamplePlugin, ExampleRpc.Data>
{
[RegisterCustomRpc((uint) CustomRpcCalls.Example)]
public class ExampleRpc : PlayerCustomRpc<ExamplePlugin, ExampleRpc.Data>
public ExampleRpc(ExamplePlugin plugin, uint id) : base(plugin, id)
{
public ExampleRpc(ExamplePlugin plugin, uint id) : base(plugin, id)
{
}
}
public readonly struct Data
{
public readonly string Message;
public readonly record struct Data(string Message);
public Data(string message)
{
Message = message;
}
}
public override RpcLocalHandling LocalHandling => RpcLocalHandling.None;
public override RpcLocalHandling LocalHandling => RpcLocalHandling.None;
public override void Write(MessageWriter writer, Data data)
{
writer.Write(data.Message);
}
public override void Write(MessageWriter writer, Data data)
{
writer.Write(data.Message);
}
public override Data Read(MessageReader reader)
{
return new Data(reader.ReadString());
}
public override Data Read(MessageReader reader)
{
return new Data(reader.ReadString());
}
public override void Handle(PlayerControl innerNetObject, Data data)
{
Plugin.Log.LogWarning($"Handle: {innerNetObject.Data.PlayerName} sent \"{data.Message}\"");
}
public override void Handle(PlayerControl innerNetObject, Data data)
{
Plugin.Log.LogWarning($"Handle: {innerNetObject.Data.PlayerName} sent \"{data.Message}\"");
}
}
+1 -4
View File
@@ -1,15 +1,12 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>netstandard2.1</TargetFramework>
<LangVersion>latest</LangVersion>
<Version>0.1.0</Version>
<Description>Example mod using Reactor</Description>
<Authors>NuclearPowered</Authors>
</PropertyGroup>
<ItemGroup>
<ProjectReference Include="..\Reactor\Reactor.csproj" />
<ProjectReference Include="..\Reactor\Reactor.csproj" Private="false" />
</ItemGroup>
<Import Project="../AmongUs.props" />
+875
View File
@@ -0,0 +1,875 @@
{
"version": 1,
"dependencies": {
"net6.0": {
"AmongUs.GameLibs.Steam": {
"type": "Direct",
"requested": "[2022.12.8, )",
"resolved": "2022.12.8",
"contentHash": "IJsIi89xUYRvA54YtNVEJjf25hhF3LWzkNBslKCNDUpL1aQ/PhNyO4j18pO71DCgW/qr1P1j8+CwByuBLsInNA=="
},
"BepInEx.AutoPlugin": {
"type": "Direct",
"requested": "[1.1.0, )",
"resolved": "1.1.0",
"contentHash": "/7Nmc1EA9lYlGBiyz6qPAaHvlcJHEjFZ1RFpGX+8EBj3GrgoX5kbpnZusuSHoOlLx0l+CnzKuQNE54B8UaGPyw=="
},
"BepInEx.IL2CPP.MSBuild": {
"type": "Direct",
"requested": "[2.0.1, )",
"resolved": "2.0.1",
"contentHash": "hUZjCV0t8dkw/Z/zq4Zl405QP7frBk/LVfMdUmUz+7XOhGd7lYPKrR48A5vbGl2QeHudMxlkXzAr9WM3Duq2SQ=="
},
"BepInEx.Unity.IL2CPP": {
"type": "Direct",
"requested": "[6.0.0-be.663, )",
"resolved": "6.0.0-be.663",
"contentHash": "J+mZ4svyTt4ZYbUoPwpVtF5QCGfzC42VuYJ7z1K6Qt8YlBEZx3rnmUmaEnoJIqN5wN7BSnQgzEmrRfdbrgtTnA==",
"dependencies": {
"BepInEx.Core": "6.0.0-be.663",
"BepInEx.Unity.Common": "6.0.0-be.663",
"HarmonyX": "2.10.1",
"Iced": "1.17.0",
"Il2CppInterop.Generator": "1.4.0",
"Il2CppInterop.HarmonySupport": "1.4.0",
"Il2CppInterop.Runtime": "1.4.0",
"MonoMod.RuntimeDetour": "22.5.1.1",
"Samboy063.Cpp2IL.Core": "2022.0.7.2"
}
},
"StyleCop.Analyzers": {
"type": "Direct",
"requested": "[1.2.0-beta.435, )",
"resolved": "1.2.0-beta.435",
"contentHash": "TADk7vdGXtfTnYCV7GyleaaRTQjfoSfZXprQrVMm7cSJtJbFc1QIbWPyLvrgrfGdfHbGmUPvaN4ODKNxg2jgPQ==",
"dependencies": {
"StyleCop.Analyzers.Unstable": "1.2.0.435"
}
},
"AssetRipper.VersionUtilities": {
"type": "Transitive",
"resolved": "1.2.1",
"contentHash": "knQ/W1YwTZS2AbdaZh+nhyyBEZQPQDcahhSOnh88i+cdg4/FEoFJiCwaavgFvCMNuUeHTbcZc4qttF8WQ8xLIA=="
},
"BepInEx.Core": {
"type": "Transitive",
"resolved": "6.0.0-be.663",
"contentHash": "yTlqwieyV3FCzSo4tfiIlS7pTqVtEZwrwHnograkWO4loECeYpShcpoCoxnhQ0vkWsnWGThMK7NodHhjZ+jQDA==",
"dependencies": {
"HarmonyX": "2.10.1",
"MonoMod.Utils": "22.5.1.1",
"SemanticVersioning": "2.0.2"
}
},
"BepInEx.Unity.Common": {
"type": "Transitive",
"resolved": "6.0.0-be.663",
"contentHash": "kxv0yXJQ7YPzUQzlwkpVzmTkdd87kVcQhMjkrwqpowJ0Yx5vEwPUrRyG/pwMH5/cK+2WHCn/2akGWrW0C4vUAQ==",
"dependencies": {
"AssetRipper.VersionUtilities": "1.2.1",
"MonoMod.Utils": "22.5.1.1"
}
},
"HarmonyX": {
"type": "Transitive",
"resolved": "2.10.1",
"contentHash": "9LodMC9Y0u1TW96eKJoWrFJFpmzbgojEO38/Q+e7c1mFPhmHt8xcR8qhI06iF1rf0Dnsk+hqENFVSgbtwl/bEw==",
"dependencies": {
"MonoMod.RuntimeDetour": "22.3.23.4",
"System.Reflection.Emit": "4.7.0"
}
},
"Iced": {
"type": "Transitive",
"resolved": "1.17.0",
"contentHash": "8x+HCVTl/HHTGpscH3vMBhV8sknN/muZFw9s3TsI8SA6+c43cOTCi2+jE4KsU8pNLbJ++iF2ZFcpcXHXtDglnw=="
},
"Il2CppInterop.Common": {
"type": "Transitive",
"resolved": "1.4.0",
"contentHash": "xl60qoa1nImG6qgOQcjSDW46nLQHoRvSWE7QTDQz7XeMsGwOxAbgDtOvJ4gOvoLijTU79gFZYe8H1CM7TcTQ5g==",
"dependencies": {
"Iced": "1.17.0",
"Microsoft.Extensions.Logging.Abstractions": "6.0.1",
"System.Net.Http": "4.3.4"
}
},
"Il2CppInterop.Generator": {
"type": "Transitive",
"resolved": "1.4.0",
"contentHash": "Q4QqkwQroDwwqB17/DRF6hbHQRIuyLksgxVUEDvXZ3T+ogkrZB9h0Ev36alN0f6e7fcZPRkMrpXOAYwZzPiZag==",
"dependencies": {
"Il2CppInterop.Common": "1.4.0",
"Mono.Cecil": "0.11.3"
}
},
"Il2CppInterop.HarmonySupport": {
"type": "Transitive",
"resolved": "1.4.0",
"contentHash": "Uz4w5PbQ3kLXqUrsQxR35f7xMpfnxLiXthVtNaT3fvHXC8B7arjuBZXeCbcozr6dXFJBDa5W0EElBmH0fWoASg==",
"dependencies": {
"HarmonyX": "2.10.0",
"Il2CppInterop.Runtime": "1.4.0"
}
},
"Il2CppInterop.Runtime": {
"type": "Transitive",
"resolved": "1.4.0",
"contentHash": "ScgsFlbJ3gj5f69As/GT8pSO2WlS7cOeS/n3h4gBqJ01Eq/Lm+s3FBrGpEiuIWALOgmtQYimhjWVpxRt7LYtGw==",
"dependencies": {
"Iced": "1.17.0",
"Il2CppInterop.Common": "1.4.0"
}
},
"IndexRange": {
"type": "Transitive",
"resolved": "1.0.0",
"contentHash": "6TgS1JLSUkpmPLfXBPaAgB39ZUix8E4soXWk2XSDcscVe84i1JKzIAtA7jHbRHSkOOrcr6YA0MpLCeq98y9mYQ=="
},
"js6pak.Gee.External.Capstone": {
"type": "Transitive",
"resolved": "2.1.0",
"contentHash": "YYpq7NM50bSSVUDjXyV/eiITk6syXqItPjKBOb3jEWS6RFsk0DNhpWMPW6b3hKDmArARuWDU6S2pVu1IeVrvIA=="
},
"Microsoft.Extensions.Logging.Abstractions": {
"type": "Transitive",
"resolved": "6.0.1",
"contentHash": "dzB2Cgg+JmrouhjkcQGzSFjjvpwlq353i8oBQO2GWNjCXSzhbtBRUf28HSauWe7eib3wYOdb3tItdjRwAdwCSg=="
},
"Microsoft.NETCore.Platforms": {
"type": "Transitive",
"resolved": "1.1.1",
"contentHash": "TMBuzAHpTenGbGgk0SMTwyEkyijY/Eae4ZGsFNYJvAr/LDn1ku3Etp3FPxChmDp5HHF3kzJuoaa08N0xjqAJfQ=="
},
"Microsoft.NETCore.Targets": {
"type": "Transitive",
"resolved": "1.1.0",
"contentHash": "aOZA3BWfz9RXjpzt0sRJJMjAscAUm3Hoa4UWAfceV9UTYxgwZ1lZt5nO2myFf+/jetYQo4uTP7zS8sJY67BBxg=="
},
"Mono.Cecil": {
"type": "Transitive",
"resolved": "0.11.4",
"contentHash": "IC1h5g0NeJGHIUgzM1P82ld57knhP0IcQfrYITDPXlNpMYGUrsG5TxuaWTjaeqDNQMBDNZkB8L0rBnwsY6JHuQ=="
},
"MonoMod.RuntimeDetour": {
"type": "Transitive",
"resolved": "22.5.1.1",
"contentHash": "WG5zLRuAr8KJEnIkKTuIG1OJCrGIT3pjvnAD43E0FDchHf3Dp985MF/8tmIQvAzCZV87JNs6QKeGGqmwDmpXpw==",
"dependencies": {
"Mono.Cecil": "0.11.4",
"MonoMod.Utils": "22.5.1.1",
"System.Collections.NonGeneric": "4.3.0",
"System.ComponentModel.TypeConverter": "4.3.0",
"System.IO.FileSystem.Primitives": "4.3.0",
"System.Reflection.Emit.ILGeneration": "4.7.0",
"System.Reflection.Emit.Lightweight": "4.7.0",
"System.Reflection.TypeExtensions": "4.7.0"
}
},
"MonoMod.Utils": {
"type": "Transitive",
"resolved": "22.5.1.1",
"contentHash": "vBObO1atXxhi2C4AuC53y87Bqeogi9xIrD1Ym3YWr5uxc8Nrm8SrsFeD1i3x04R999+XQ3FdeHrbXScyWYEHqQ==",
"dependencies": {
"Mono.Cecil": "0.11.4",
"System.Collections.NonGeneric": "4.3.0",
"System.ComponentModel.TypeConverter": "4.3.0",
"System.IO.FileSystem.Primitives": "4.3.0",
"System.Reflection.Emit.ILGeneration": "4.7.0",
"System.Reflection.Emit.Lightweight": "4.7.0",
"System.Reflection.TypeExtensions": "4.7.0"
}
},
"runtime.debian.8-x64.runtime.native.System.Security.Cryptography.OpenSsl": {
"type": "Transitive",
"resolved": "4.3.2",
"contentHash": "7VSGO0URRKoMEAq0Sc9cRz8mb6zbyx/BZDEWhgPdzzpmFhkam3fJ1DAGWFXBI4nGlma+uPKpfuMQP5LXRnOH5g=="
},
"runtime.fedora.23-x64.runtime.native.System.Security.Cryptography.OpenSsl": {
"type": "Transitive",
"resolved": "4.3.2",
"contentHash": "0oAaTAm6e2oVH+/Zttt0cuhGaePQYKII1dY8iaqP7CvOpVKgLybKRFvQjXR2LtxXOXTVPNv14j0ot8uV+HrUmw=="
},
"runtime.fedora.24-x64.runtime.native.System.Security.Cryptography.OpenSsl": {
"type": "Transitive",
"resolved": "4.3.2",
"contentHash": "G24ibsCNi5Kbz0oXWynBoRgtGvsw5ZSVEWjv13/KiCAM8C6wz9zzcCniMeQFIkJ2tasjo2kXlvlBZhplL51kGg=="
},
"runtime.native.System": {
"type": "Transitive",
"resolved": "4.3.0",
"contentHash": "c/qWt2LieNZIj1jGnVNsE2Kl23Ya2aSTBuXMD6V7k9KWr6l16Tqdwq+hJScEpWER9753NWC8h96PaVNY5Ld7Jw==",
"dependencies": {
"Microsoft.NETCore.Platforms": "1.1.0",
"Microsoft.NETCore.Targets": "1.1.0"
}
},
"runtime.native.System.Net.Http": {
"type": "Transitive",
"resolved": "4.3.0",
"contentHash": "ZVuZJqnnegJhd2k/PtAbbIcZ3aZeITq3sj06oKfMBSfphW3HDmk/t4ObvbOk/JA/swGR0LNqMksAh/f7gpTROg==",
"dependencies": {
"Microsoft.NETCore.Platforms": "1.1.0",
"Microsoft.NETCore.Targets": "1.1.0"
}
},
"runtime.native.System.Security.Cryptography.Apple": {
"type": "Transitive",
"resolved": "4.3.0",
"contentHash": "DloMk88juo0OuOWr56QG7MNchmafTLYWvABy36izkrLI5VledI0rq28KGs1i9wbpeT9NPQrx/wTf8U2vazqQ3Q==",
"dependencies": {
"runtime.osx.10.10-x64.runtime.native.System.Security.Cryptography.Apple": "4.3.0"
}
},
"runtime.native.System.Security.Cryptography.OpenSsl": {
"type": "Transitive",
"resolved": "4.3.2",
"contentHash": "QR1OwtwehHxSeQvZKXe+iSd+d3XZNkEcuWMFYa2i0aG1l+lR739HPicKMlTbJst3spmeekDVBUS7SeS26s4U/g==",
"dependencies": {
"runtime.debian.8-x64.runtime.native.System.Security.Cryptography.OpenSsl": "4.3.2",
"runtime.fedora.23-x64.runtime.native.System.Security.Cryptography.OpenSsl": "4.3.2",
"runtime.fedora.24-x64.runtime.native.System.Security.Cryptography.OpenSsl": "4.3.2",
"runtime.opensuse.13.2-x64.runtime.native.System.Security.Cryptography.OpenSsl": "4.3.2",
"runtime.opensuse.42.1-x64.runtime.native.System.Security.Cryptography.OpenSsl": "4.3.2",
"runtime.osx.10.10-x64.runtime.native.System.Security.Cryptography.OpenSsl": "4.3.2",
"runtime.rhel.7-x64.runtime.native.System.Security.Cryptography.OpenSsl": "4.3.2",
"runtime.ubuntu.14.04-x64.runtime.native.System.Security.Cryptography.OpenSsl": "4.3.2",
"runtime.ubuntu.16.04-x64.runtime.native.System.Security.Cryptography.OpenSsl": "4.3.2",
"runtime.ubuntu.16.10-x64.runtime.native.System.Security.Cryptography.OpenSsl": "4.3.2"
}
},
"runtime.opensuse.13.2-x64.runtime.native.System.Security.Cryptography.OpenSsl": {
"type": "Transitive",
"resolved": "4.3.2",
"contentHash": "I+GNKGg2xCHueRd1m9PzeEW7WLbNNLznmTuEi8/vZX71HudUbx1UTwlGkiwMri7JLl8hGaIAWnA/GONhu+LOyQ=="
},
"runtime.opensuse.42.1-x64.runtime.native.System.Security.Cryptography.OpenSsl": {
"type": "Transitive",
"resolved": "4.3.2",
"contentHash": "1Z3TAq1ytS1IBRtPXJvEUZdVsfWfeNEhBkbiOCGEl9wwAfsjP2lz3ZFDx5tq8p60/EqbS0HItG5piHuB71RjoA=="
},
"runtime.osx.10.10-x64.runtime.native.System.Security.Cryptography.Apple": {
"type": "Transitive",
"resolved": "4.3.0",
"contentHash": "kVXCuMTrTlxq4XOOMAysuNwsXWpYeboGddNGpIgNSZmv1b6r/s/DPk0fYMB7Q5Qo4bY68o48jt4T4y5BVecbCQ=="
},
"runtime.osx.10.10-x64.runtime.native.System.Security.Cryptography.OpenSsl": {
"type": "Transitive",
"resolved": "4.3.2",
"contentHash": "6mU/cVmmHtQiDXhnzUImxIcDL48GbTk+TsptXyJA+MIOG9LRjPoAQC/qBFB7X+UNyK86bmvGwC8t+M66wsYC8w=="
},
"runtime.rhel.7-x64.runtime.native.System.Security.Cryptography.OpenSsl": {
"type": "Transitive",
"resolved": "4.3.2",
"contentHash": "vjwG0GGcTW/PPg6KVud8F9GLWYuAV1rrw1BKAqY0oh4jcUqg15oYF1+qkGR2x2ZHM4DQnWKQ7cJgYbfncz/lYg=="
},
"runtime.ubuntu.14.04-x64.runtime.native.System.Security.Cryptography.OpenSsl": {
"type": "Transitive",
"resolved": "4.3.2",
"contentHash": "7KMFpTkHC/zoExs+PwP8jDCWcrK9H6L7soowT80CUx3e+nxP/AFnq0AQAW5W76z2WYbLAYCRyPfwYFG6zkvQRw=="
},
"runtime.ubuntu.16.04-x64.runtime.native.System.Security.Cryptography.OpenSsl": {
"type": "Transitive",
"resolved": "4.3.2",
"contentHash": "xrlmRCnKZJLHxyyLIqkZjNXqgxnKdZxfItrPkjI+6pkRo5lHX8YvSZlWrSI5AVwLMi4HbNWP7064hcAWeZKp5w=="
},
"runtime.ubuntu.16.10-x64.runtime.native.System.Security.Cryptography.OpenSsl": {
"type": "Transitive",
"resolved": "4.3.2",
"contentHash": "leXiwfiIkW7Gmn7cgnNcdtNAU70SjmKW3jxGj1iKHOvdn0zRWsgv/l2OJUO5zdGdiv2VRFnAsxxhDgMzofPdWg=="
},
"Samboy063.Cpp2IL.Core": {
"type": "Transitive",
"resolved": "2022.0.7.2",
"contentHash": "e17CAhKSxdAp7vFcYEVxjSc7t7rcvVGBipGhgE9tAjRXY85wZXLlHEVO0AEvMRkLmf9U+if4wK/nZEC1AX6VqQ==",
"dependencies": {
"HarmonyX": "2.5.5",
"Iced": "1.11.1",
"IndexRange": "1.0.0",
"Mono.Cecil": "0.11.4",
"Samboy063.LibCpp2IL": "2022.0.7.2",
"System.Runtime.InteropServices": "4.3.0",
"System.ValueTuple": "4.5.0",
"js6pak.Gee.External.Capstone": "2.1.0"
}
},
"Samboy063.LibCpp2IL": {
"type": "Transitive",
"resolved": "2022.0.7.2",
"contentHash": "DpVeU0dQkUJCpbw0f1xKOG8vimdK2oYhrVABC7HDE3/ikGjhnMZd3i5b1joKDHZ+AiL90TWOaEXPcy24rCZ0dA==",
"dependencies": {
"IndexRange": "1.0.0",
"Samboy063.WasmDisassembler": "2022.0.2"
}
},
"Samboy063.WasmDisassembler": {
"type": "Transitive",
"resolved": "2022.0.2",
"contentHash": "2uu+xBb7M3HKfBx9tAY6jiDieAf0hRnQjSmGX+7IdE6i24dYsx6TYgtrLvRx5lOuF2M8DijZ5H8yQ1pcuCs2SA=="
},
"SemanticVersioning": {
"type": "Transitive",
"resolved": "2.0.2",
"contentHash": "4EQgYdNZ92SyaO7YFk6olVnebF5V+jrHyMUjvPq89tLeMo8NSfgDF+6Zwq/lgh9j/0yfQp9Lkm0ZA0rUATCZFA=="
},
"StyleCop.Analyzers.Unstable": {
"type": "Transitive",
"resolved": "1.2.0.435",
"contentHash": "ouwPWZxbOV3SmCZxIRqHvljkSzkCyi1tDoMzQtDb/bRP8ctASV/iRJr+A2Gdj0QLaLmWnqTWDrH82/iP+X80Lg=="
},
"System.Collections": {
"type": "Transitive",
"resolved": "4.3.0",
"contentHash": "3Dcj85/TBdVpL5Zr+gEEBUuFe2icOnLalmEh9hfck1PTYbbyWuZgh4fmm2ysCLTrqLQw6t3TgTyJ+VLp+Qb+Lw==",
"dependencies": {
"Microsoft.NETCore.Platforms": "1.1.0",
"Microsoft.NETCore.Targets": "1.1.0",
"System.Runtime": "4.3.0"
}
},
"System.Collections.Concurrent": {
"type": "Transitive",
"resolved": "4.3.0",
"contentHash": "ztl69Xp0Y/UXCL+3v3tEU+lIy+bvjKNUmopn1wep/a291pVPK7dxBd6T7WnlQqRog+d1a/hSsgRsmFnIBKTPLQ==",
"dependencies": {
"System.Collections": "4.3.0",
"System.Diagnostics.Debug": "4.3.0",
"System.Diagnostics.Tracing": "4.3.0",
"System.Globalization": "4.3.0",
"System.Reflection": "4.3.0",
"System.Resources.ResourceManager": "4.3.0",
"System.Runtime": "4.3.0",
"System.Runtime.Extensions": "4.3.0",
"System.Threading": "4.3.0",
"System.Threading.Tasks": "4.3.0"
}
},
"System.Collections.NonGeneric": {
"type": "Transitive",
"resolved": "4.3.0",
"contentHash": "prtjIEMhGUnQq6RnPEYLpFt8AtLbp9yq2zxOSrY7KJJZrw25Fi97IzBqY7iqssbM61Ek5b8f3MG/sG1N2sN5KA==",
"dependencies": {
"System.Diagnostics.Debug": "4.3.0",
"System.Globalization": "4.3.0",
"System.Resources.ResourceManager": "4.3.0",
"System.Runtime": "4.3.0",
"System.Runtime.Extensions": "4.3.0",
"System.Threading": "4.3.0"
}
},
"System.Collections.Specialized": {
"type": "Transitive",
"resolved": "4.3.0",
"contentHash": "Epx8PoVZR0iuOnJJDzp7pWvdfMMOAvpUo95pC4ScH2mJuXkKA2Y4aR3cG9qt2klHgSons1WFh4kcGW7cSXvrxg==",
"dependencies": {
"System.Collections.NonGeneric": "4.3.0",
"System.Globalization": "4.3.0",
"System.Globalization.Extensions": "4.3.0",
"System.Resources.ResourceManager": "4.3.0",
"System.Runtime": "4.3.0",
"System.Runtime.Extensions": "4.3.0",
"System.Threading": "4.3.0"
}
},
"System.ComponentModel": {
"type": "Transitive",
"resolved": "4.3.0",
"contentHash": "VyGn1jGRZVfxnh8EdvDCi71v3bMXrsu8aYJOwoV7SNDLVhiEqwP86pPMyRGsDsxhXAm2b3o9OIqeETfN5qfezw==",
"dependencies": {
"System.Runtime": "4.3.0"
}
},
"System.ComponentModel.Primitives": {
"type": "Transitive",
"resolved": "4.3.0",
"contentHash": "j8GUkCpM8V4d4vhLIIoBLGey2Z5bCkMVNjEZseyAlm4n5arcsJOeI3zkUP+zvZgzsbLTYh4lYeP/ZD/gdIAPrw==",
"dependencies": {
"System.ComponentModel": "4.3.0",
"System.Resources.ResourceManager": "4.3.0",
"System.Runtime": "4.3.0"
}
},
"System.ComponentModel.TypeConverter": {
"type": "Transitive",
"resolved": "4.3.0",
"contentHash": "16pQ6P+EdhcXzPiEK4kbA953Fu0MNG2ovxTZU81/qsCd1zPRsKc3uif5NgvllCY598k6bI0KUyKW8fanlfaDQg==",
"dependencies": {
"System.Collections": "4.3.0",
"System.Collections.NonGeneric": "4.3.0",
"System.Collections.Specialized": "4.3.0",
"System.ComponentModel": "4.3.0",
"System.ComponentModel.Primitives": "4.3.0",
"System.Globalization": "4.3.0",
"System.Linq": "4.3.0",
"System.Reflection": "4.3.0",
"System.Reflection.Extensions": "4.3.0",
"System.Reflection.Primitives": "4.3.0",
"System.Reflection.TypeExtensions": "4.3.0",
"System.Resources.ResourceManager": "4.3.0",
"System.Runtime": "4.3.0",
"System.Runtime.Extensions": "4.3.0",
"System.Threading": "4.3.0"
}
},
"System.Diagnostics.Debug": {
"type": "Transitive",
"resolved": "4.3.0",
"contentHash": "ZUhUOdqmaG5Jk3Xdb8xi5kIyQYAA4PnTNlHx1mu9ZY3qv4ELIdKbnL/akbGaKi2RnNUWaZsAs31rvzFdewTj2g==",
"dependencies": {
"Microsoft.NETCore.Platforms": "1.1.0",
"Microsoft.NETCore.Targets": "1.1.0",
"System.Runtime": "4.3.0"
}
},
"System.Diagnostics.DiagnosticSource": {
"type": "Transitive",
"resolved": "4.3.0",
"contentHash": "tD6kosZnTAGdrEa0tZSuFyunMbt/5KYDnHdndJYGqZoNy00XVXyACd5d6KnE1YgYv3ne2CjtAfNXo/fwEhnKUA==",
"dependencies": {
"System.Collections": "4.3.0",
"System.Diagnostics.Tracing": "4.3.0",
"System.Reflection": "4.3.0",
"System.Runtime": "4.3.0",
"System.Threading": "4.3.0"
}
},
"System.Diagnostics.Tracing": {
"type": "Transitive",
"resolved": "4.3.0",
"contentHash": "rswfv0f/Cqkh78rA5S8eN8Neocz234+emGCtTF3lxPY96F+mmmUen6tbn0glN6PMvlKQb9bPAY5e9u7fgPTkKw==",
"dependencies": {
"Microsoft.NETCore.Platforms": "1.1.0",
"Microsoft.NETCore.Targets": "1.1.0",
"System.Runtime": "4.3.0"
}
},
"System.Globalization": {
"type": "Transitive",
"resolved": "4.3.0",
"contentHash": "kYdVd2f2PAdFGblzFswE4hkNANJBKRmsfa2X5LG2AcWE1c7/4t0pYae1L8vfZ5xvE2nK/R9JprtToA61OSHWIg==",
"dependencies": {
"Microsoft.NETCore.Platforms": "1.1.0",
"Microsoft.NETCore.Targets": "1.1.0",
"System.Runtime": "4.3.0"
}
},
"System.Globalization.Calendars": {
"type": "Transitive",
"resolved": "4.3.0",
"contentHash": "GUlBtdOWT4LTV3I+9/PJW+56AnnChTaOqqTLFtdmype/L500M2LIyXgmtd9X2P2VOkmJd5c67H5SaC2QcL1bFA==",
"dependencies": {
"Microsoft.NETCore.Platforms": "1.1.0",
"Microsoft.NETCore.Targets": "1.1.0",
"System.Globalization": "4.3.0",
"System.Runtime": "4.3.0"
}
},
"System.Globalization.Extensions": {
"type": "Transitive",
"resolved": "4.3.0",
"contentHash": "FhKmdR6MPG+pxow6wGtNAWdZh7noIOpdD5TwQ3CprzgIE1bBBoim0vbR1+AWsWjQmU7zXHgQo4TWSP6lCeiWcQ==",
"dependencies": {
"Microsoft.NETCore.Platforms": "1.1.0",
"System.Globalization": "4.3.0",
"System.Resources.ResourceManager": "4.3.0",
"System.Runtime": "4.3.0",
"System.Runtime.Extensions": "4.3.0",
"System.Runtime.InteropServices": "4.3.0"
}
},
"System.IO": {
"type": "Transitive",
"resolved": "4.3.0",
"contentHash": "3qjaHvxQPDpSOYICjUoTsmoq5u6QJAFRUITgeT/4gqkF1bajbSmb1kwSxEA8AHlofqgcKJcM8udgieRNhaJ5Cg==",
"dependencies": {
"Microsoft.NETCore.Platforms": "1.1.0",
"Microsoft.NETCore.Targets": "1.1.0",
"System.Runtime": "4.3.0",
"System.Text.Encoding": "4.3.0",
"System.Threading.Tasks": "4.3.0"
}
},
"System.IO.FileSystem": {
"type": "Transitive",
"resolved": "4.3.0",
"contentHash": "3wEMARTnuio+ulnvi+hkRNROYwa1kylvYahhcLk4HSoVdl+xxTFVeVlYOfLwrDPImGls0mDqbMhrza8qnWPTdA==",
"dependencies": {
"Microsoft.NETCore.Platforms": "1.1.0",
"Microsoft.NETCore.Targets": "1.1.0",
"System.IO": "4.3.0",
"System.IO.FileSystem.Primitives": "4.3.0",
"System.Runtime": "4.3.0",
"System.Runtime.Handles": "4.3.0",
"System.Text.Encoding": "4.3.0",
"System.Threading.Tasks": "4.3.0"
}
},
"System.IO.FileSystem.Primitives": {
"type": "Transitive",
"resolved": "4.3.0",
"contentHash": "6QOb2XFLch7bEc4lIcJH49nJN2HV+OC3fHDgsLVsBVBk3Y4hFAnOBGzJ2lUu7CyDDFo9IBWkSsnbkT6IBwwiMw==",
"dependencies": {
"System.Runtime": "4.3.0"
}
},
"System.Linq": {
"type": "Transitive",
"resolved": "4.3.0",
"contentHash": "5DbqIUpsDp0dFftytzuMmc0oeMdQwjcP/EWxsksIz/w1TcFRkZ3yKKz0PqiYFMmEwPSWw+qNVqD7PJ889JzHbw==",
"dependencies": {
"System.Collections": "4.3.0",
"System.Diagnostics.Debug": "4.3.0",
"System.Resources.ResourceManager": "4.3.0",
"System.Runtime": "4.3.0",
"System.Runtime.Extensions": "4.3.0"
}
},
"System.Net.Http": {
"type": "Transitive",
"resolved": "4.3.4",
"contentHash": "aOa2d51SEbmM+H+Csw7yJOuNZoHkrP2XnAurye5HWYgGVVU54YZDvsLUYRv6h18X3sPnjNCANmN7ZhIPiqMcjA==",
"dependencies": {
"Microsoft.NETCore.Platforms": "1.1.1",
"System.Collections": "4.3.0",
"System.Diagnostics.Debug": "4.3.0",
"System.Diagnostics.DiagnosticSource": "4.3.0",
"System.Diagnostics.Tracing": "4.3.0",
"System.Globalization": "4.3.0",
"System.Globalization.Extensions": "4.3.0",
"System.IO": "4.3.0",
"System.IO.FileSystem": "4.3.0",
"System.Net.Primitives": "4.3.0",
"System.Resources.ResourceManager": "4.3.0",
"System.Runtime": "4.3.0",
"System.Runtime.Extensions": "4.3.0",
"System.Runtime.Handles": "4.3.0",
"System.Runtime.InteropServices": "4.3.0",
"System.Security.Cryptography.Algorithms": "4.3.0",
"System.Security.Cryptography.Encoding": "4.3.0",
"System.Security.Cryptography.OpenSsl": "4.3.0",
"System.Security.Cryptography.Primitives": "4.3.0",
"System.Security.Cryptography.X509Certificates": "4.3.0",
"System.Text.Encoding": "4.3.0",
"System.Threading": "4.3.0",
"System.Threading.Tasks": "4.3.0",
"runtime.native.System": "4.3.0",
"runtime.native.System.Net.Http": "4.3.0",
"runtime.native.System.Security.Cryptography.OpenSsl": "4.3.2"
}
},
"System.Net.Primitives": {
"type": "Transitive",
"resolved": "4.3.0",
"contentHash": "qOu+hDwFwoZPbzPvwut2qATe3ygjeQBDQj91xlsaqGFQUI5i4ZnZb8yyQuLGpDGivEPIt8EJkd1BVzVoP31FXA==",
"dependencies": {
"Microsoft.NETCore.Platforms": "1.1.0",
"Microsoft.NETCore.Targets": "1.1.0",
"System.Runtime": "4.3.0",
"System.Runtime.Handles": "4.3.0"
}
},
"System.Reflection": {
"type": "Transitive",
"resolved": "4.3.0",
"contentHash": "KMiAFoW7MfJGa9nDFNcfu+FpEdiHpWgTcS2HdMpDvt9saK3y/G4GwprPyzqjFH9NTaGPQeWNHU+iDlDILj96aQ==",
"dependencies": {
"Microsoft.NETCore.Platforms": "1.1.0",
"Microsoft.NETCore.Targets": "1.1.0",
"System.IO": "4.3.0",
"System.Reflection.Primitives": "4.3.0",
"System.Runtime": "4.3.0"
}
},
"System.Reflection.Emit": {
"type": "Transitive",
"resolved": "4.7.0",
"contentHash": "VR4kk8XLKebQ4MZuKuIni/7oh+QGFmZW3qORd1GvBq/8026OpW501SzT/oypwiQl4TvT8ErnReh/NzY9u+C6wQ=="
},
"System.Reflection.Emit.ILGeneration": {
"type": "Transitive",
"resolved": "4.7.0",
"contentHash": "AucBYo3DSI0IDxdUjKksBcQJXPHyoPyrCXYURW1WDsLI4M65Ar/goSHjdnHOAY9MiYDNKqDlIgaYm+zL2hA1KA=="
},
"System.Reflection.Emit.Lightweight": {
"type": "Transitive",
"resolved": "4.7.0",
"contentHash": "a4OLB4IITxAXJeV74MDx49Oq2+PsF6Sml54XAFv+2RyWwtDBcabzoxiiJRhdhx+gaohLh4hEGCLQyBozXoQPqA=="
},
"System.Reflection.Extensions": {
"type": "Transitive",
"resolved": "4.3.0",
"contentHash": "rJkrJD3kBI5B712aRu4DpSIiHRtr6QlfZSQsb0hYHrDCZORXCFjQfoipo2LaMUHoT9i1B7j7MnfaEKWDFmFQNQ==",
"dependencies": {
"Microsoft.NETCore.Platforms": "1.1.0",
"Microsoft.NETCore.Targets": "1.1.0",
"System.Reflection": "4.3.0",
"System.Runtime": "4.3.0"
}
},
"System.Reflection.Primitives": {
"type": "Transitive",
"resolved": "4.3.0",
"contentHash": "5RXItQz5As4xN2/YUDxdpsEkMhvw3e6aNveFXUn4Hl/udNTCNhnKp8lT9fnc3MhvGKh1baak5CovpuQUXHAlIA==",
"dependencies": {
"Microsoft.NETCore.Platforms": "1.1.0",
"Microsoft.NETCore.Targets": "1.1.0",
"System.Runtime": "4.3.0"
}
},
"System.Reflection.TypeExtensions": {
"type": "Transitive",
"resolved": "4.7.0",
"contentHash": "VybpaOQQhqE6siHppMktjfGBw1GCwvCqiufqmP8F1nj7fTUNtW35LOEt3UZTEsECfo+ELAl/9o9nJx3U91i7vA=="
},
"System.Resources.ResourceManager": {
"type": "Transitive",
"resolved": "4.3.0",
"contentHash": "/zrcPkkWdZmI4F92gL/TPumP98AVDu/Wxr3CSJGQQ+XN6wbRZcyfSKVoPo17ilb3iOr0cCRqJInGwNMolqhS8A==",
"dependencies": {
"Microsoft.NETCore.Platforms": "1.1.0",
"Microsoft.NETCore.Targets": "1.1.0",
"System.Globalization": "4.3.0",
"System.Reflection": "4.3.0",
"System.Runtime": "4.3.0"
}
},
"System.Runtime": {
"type": "Transitive",
"resolved": "4.3.0",
"contentHash": "JufQi0vPQ0xGnAczR13AUFglDyVYt4Kqnz1AZaiKZ5+GICq0/1MH/mO/eAJHt/mHW1zjKBJd7kV26SrxddAhiw==",
"dependencies": {
"Microsoft.NETCore.Platforms": "1.1.0",
"Microsoft.NETCore.Targets": "1.1.0"
}
},
"System.Runtime.Extensions": {
"type": "Transitive",
"resolved": "4.3.0",
"contentHash": "guW0uK0fn5fcJJ1tJVXYd7/1h5F+pea1r7FLSOz/f8vPEqbR2ZAknuRDvTQ8PzAilDveOxNjSfr0CHfIQfFk8g==",
"dependencies": {
"Microsoft.NETCore.Platforms": "1.1.0",
"Microsoft.NETCore.Targets": "1.1.0",
"System.Runtime": "4.3.0"
}
},
"System.Runtime.Handles": {
"type": "Transitive",
"resolved": "4.3.0",
"contentHash": "OKiSUN7DmTWeYb3l51A7EYaeNMnvxwE249YtZz7yooT4gOZhmTjIn48KgSsw2k2lYdLgTKNJw/ZIfSElwDRVgg==",
"dependencies": {
"Microsoft.NETCore.Platforms": "1.1.0",
"Microsoft.NETCore.Targets": "1.1.0",
"System.Runtime": "4.3.0"
}
},
"System.Runtime.InteropServices": {
"type": "Transitive",
"resolved": "4.3.0",
"contentHash": "uv1ynXqiMK8mp1GM3jDqPCFN66eJ5w5XNomaK2XD+TuCroNTLFGeZ+WCmBMcBDyTFKou3P6cR6J/QsaqDp7fGQ==",
"dependencies": {
"Microsoft.NETCore.Platforms": "1.1.0",
"Microsoft.NETCore.Targets": "1.1.0",
"System.Reflection": "4.3.0",
"System.Reflection.Primitives": "4.3.0",
"System.Runtime": "4.3.0",
"System.Runtime.Handles": "4.3.0"
}
},
"System.Runtime.Numerics": {
"type": "Transitive",
"resolved": "4.3.0",
"contentHash": "yMH+MfdzHjy17l2KESnPiF2dwq7T+xLnSJar7slyimAkUh/gTrS9/UQOtv7xarskJ2/XDSNvfLGOBQPjL7PaHQ==",
"dependencies": {
"System.Globalization": "4.3.0",
"System.Resources.ResourceManager": "4.3.0",
"System.Runtime": "4.3.0",
"System.Runtime.Extensions": "4.3.0"
}
},
"System.Security.Cryptography.Algorithms": {
"type": "Transitive",
"resolved": "4.3.0",
"contentHash": "W1kd2Y8mYSCgc3ULTAZ0hOP2dSdG5YauTb1089T0/kRcN2MpSAW1izOFROrJgxSlMn3ArsgHXagigyi+ibhevg==",
"dependencies": {
"Microsoft.NETCore.Platforms": "1.1.0",
"System.Collections": "4.3.0",
"System.IO": "4.3.0",
"System.Resources.ResourceManager": "4.3.0",
"System.Runtime": "4.3.0",
"System.Runtime.Extensions": "4.3.0",
"System.Runtime.Handles": "4.3.0",
"System.Runtime.InteropServices": "4.3.0",
"System.Runtime.Numerics": "4.3.0",
"System.Security.Cryptography.Encoding": "4.3.0",
"System.Security.Cryptography.Primitives": "4.3.0",
"System.Text.Encoding": "4.3.0",
"runtime.native.System.Security.Cryptography.Apple": "4.3.0",
"runtime.native.System.Security.Cryptography.OpenSsl": "4.3.0"
}
},
"System.Security.Cryptography.Cng": {
"type": "Transitive",
"resolved": "4.3.0",
"contentHash": "03idZOqFlsKRL4W+LuCpJ6dBYDUWReug6lZjBa3uJWnk5sPCUXckocevTaUA8iT/MFSrY/2HXkOt753xQ/cf8g==",
"dependencies": {
"Microsoft.NETCore.Platforms": "1.1.0",
"System.IO": "4.3.0",
"System.Resources.ResourceManager": "4.3.0",
"System.Runtime": "4.3.0",
"System.Runtime.Extensions": "4.3.0",
"System.Runtime.Handles": "4.3.0",
"System.Runtime.InteropServices": "4.3.0",
"System.Security.Cryptography.Algorithms": "4.3.0",
"System.Security.Cryptography.Encoding": "4.3.0",
"System.Security.Cryptography.Primitives": "4.3.0",
"System.Text.Encoding": "4.3.0"
}
},
"System.Security.Cryptography.Csp": {
"type": "Transitive",
"resolved": "4.3.0",
"contentHash": "X4s/FCkEUnRGnwR3aSfVIkldBmtURMhmexALNTwpjklzxWU7yjMk7GHLKOZTNkgnWnE0q7+BCf9N2LVRWxewaA==",
"dependencies": {
"Microsoft.NETCore.Platforms": "1.1.0",
"System.IO": "4.3.0",
"System.Reflection": "4.3.0",
"System.Resources.ResourceManager": "4.3.0",
"System.Runtime": "4.3.0",
"System.Runtime.Extensions": "4.3.0",
"System.Runtime.Handles": "4.3.0",
"System.Runtime.InteropServices": "4.3.0",
"System.Security.Cryptography.Algorithms": "4.3.0",
"System.Security.Cryptography.Encoding": "4.3.0",
"System.Security.Cryptography.Primitives": "4.3.0",
"System.Text.Encoding": "4.3.0",
"System.Threading": "4.3.0"
}
},
"System.Security.Cryptography.Encoding": {
"type": "Transitive",
"resolved": "4.3.0",
"contentHash": "1DEWjZZly9ae9C79vFwqaO5kaOlI5q+3/55ohmq/7dpDyDfc8lYe7YVxJUZ5MF/NtbkRjwFRo14yM4OEo9EmDw==",
"dependencies": {
"Microsoft.NETCore.Platforms": "1.1.0",
"System.Collections": "4.3.0",
"System.Collections.Concurrent": "4.3.0",
"System.Linq": "4.3.0",
"System.Resources.ResourceManager": "4.3.0",
"System.Runtime": "4.3.0",
"System.Runtime.Extensions": "4.3.0",
"System.Runtime.Handles": "4.3.0",
"System.Runtime.InteropServices": "4.3.0",
"System.Security.Cryptography.Primitives": "4.3.0",
"System.Text.Encoding": "4.3.0",
"runtime.native.System.Security.Cryptography.OpenSsl": "4.3.0"
}
},
"System.Security.Cryptography.OpenSsl": {
"type": "Transitive",
"resolved": "4.3.0",
"contentHash": "h4CEgOgv5PKVF/HwaHzJRiVboL2THYCou97zpmhjghx5frc7fIvlkY1jL+lnIQyChrJDMNEXS6r7byGif8Cy4w==",
"dependencies": {
"System.Collections": "4.3.0",
"System.IO": "4.3.0",
"System.Resources.ResourceManager": "4.3.0",
"System.Runtime": "4.3.0",
"System.Runtime.Extensions": "4.3.0",
"System.Runtime.Handles": "4.3.0",
"System.Runtime.InteropServices": "4.3.0",
"System.Runtime.Numerics": "4.3.0",
"System.Security.Cryptography.Algorithms": "4.3.0",
"System.Security.Cryptography.Encoding": "4.3.0",
"System.Security.Cryptography.Primitives": "4.3.0",
"System.Text.Encoding": "4.3.0",
"runtime.native.System.Security.Cryptography.OpenSsl": "4.3.0"
}
},
"System.Security.Cryptography.Primitives": {
"type": "Transitive",
"resolved": "4.3.0",
"contentHash": "7bDIyVFNL/xKeFHjhobUAQqSpJq9YTOpbEs6mR233Et01STBMXNAc/V+BM6dwYGc95gVh/Zf+iVXWzj3mE8DWg==",
"dependencies": {
"System.Diagnostics.Debug": "4.3.0",
"System.Globalization": "4.3.0",
"System.IO": "4.3.0",
"System.Resources.ResourceManager": "4.3.0",
"System.Runtime": "4.3.0",
"System.Threading": "4.3.0",
"System.Threading.Tasks": "4.3.0"
}
},
"System.Security.Cryptography.X509Certificates": {
"type": "Transitive",
"resolved": "4.3.0",
"contentHash": "t2Tmu6Y2NtJ2um0RtcuhP7ZdNNxXEgUm2JeoA/0NvlMjAhKCnM1NX07TDl3244mVp3QU6LPEhT3HTtH1uF7IYw==",
"dependencies": {
"Microsoft.NETCore.Platforms": "1.1.0",
"System.Collections": "4.3.0",
"System.Diagnostics.Debug": "4.3.0",
"System.Globalization": "4.3.0",
"System.Globalization.Calendars": "4.3.0",
"System.IO": "4.3.0",
"System.IO.FileSystem": "4.3.0",
"System.IO.FileSystem.Primitives": "4.3.0",
"System.Resources.ResourceManager": "4.3.0",
"System.Runtime": "4.3.0",
"System.Runtime.Extensions": "4.3.0",
"System.Runtime.Handles": "4.3.0",
"System.Runtime.InteropServices": "4.3.0",
"System.Runtime.Numerics": "4.3.0",
"System.Security.Cryptography.Algorithms": "4.3.0",
"System.Security.Cryptography.Cng": "4.3.0",
"System.Security.Cryptography.Csp": "4.3.0",
"System.Security.Cryptography.Encoding": "4.3.0",
"System.Security.Cryptography.OpenSsl": "4.3.0",
"System.Security.Cryptography.Primitives": "4.3.0",
"System.Text.Encoding": "4.3.0",
"System.Threading": "4.3.0",
"runtime.native.System": "4.3.0",
"runtime.native.System.Net.Http": "4.3.0",
"runtime.native.System.Security.Cryptography.OpenSsl": "4.3.0"
}
},
"System.Text.Encoding": {
"type": "Transitive",
"resolved": "4.3.0",
"contentHash": "BiIg+KWaSDOITze6jGQynxg64naAPtqGHBwDrLaCtixsa5bKiR8dpPOHA7ge3C0JJQizJE+sfkz1wV+BAKAYZw==",
"dependencies": {
"Microsoft.NETCore.Platforms": "1.1.0",
"Microsoft.NETCore.Targets": "1.1.0",
"System.Runtime": "4.3.0"
}
},
"System.Threading": {
"type": "Transitive",
"resolved": "4.3.0",
"contentHash": "VkUS0kOBcUf3Wwm0TSbrevDDZ6BlM+b/HRiapRFWjM5O0NS0LviG0glKmFK+hhPDd1XFeSdU1GmlLhb2CoVpIw==",
"dependencies": {
"System.Runtime": "4.3.0",
"System.Threading.Tasks": "4.3.0"
}
},
"System.Threading.Tasks": {
"type": "Transitive",
"resolved": "4.3.0",
"contentHash": "LbSxKEdOUhVe8BezB/9uOGGppt+nZf6e1VFyw6v3DN6lqitm0OSn2uXMOdtP0M3W4iMcqcivm2J6UgqiwwnXiA==",
"dependencies": {
"Microsoft.NETCore.Platforms": "1.1.0",
"Microsoft.NETCore.Targets": "1.1.0",
"System.Runtime": "4.3.0"
}
},
"System.ValueTuple": {
"type": "Transitive",
"resolved": "4.5.0",
"contentHash": "okurQJO6NRE/apDIP23ajJ0hpiNmJ+f0BwOlB/cSqTLQlw5upkf+5+96+iG2Jw40G1fCVCyPz/FhIABUjMR+RQ=="
},
"reactor": {
"type": "Project",
"dependencies": {
"BepInEx.Unity.IL2CPP": "[6.0.0-be.663, )"
}
}
}
}
}
+122
View File
@@ -0,0 +1,122 @@
#nullable enable
using System;
using System.Collections.Generic;
using System.Diagnostics.CodeAnalysis;
using System.Linq;
using System.Text;
namespace Reactor.Networking;
/// <summary>
/// Represents a Reactor.Protocol mod.
/// </summary>
public readonly struct Mod : IEquatable<Mod>
{
/// <summary>
/// Initializes a new instance of the <see cref="Mod"/> struct.
/// </summary>
/// <param name="id">The id of the mod.</param>
/// <param name="version">The version of the mod.</param>
/// <param name="flags">The flags of the mod.</param>
/// <param name="name">The name of the mod.</param>
public Mod(string id, string version, ModFlags flags, string? name = null)
{
Id = id;
Version = version;
Flags = flags;
Name = name;
}
/// <summary>
/// Gets the id of the mod.
/// </summary>
public string Id { get; }
/// <summary>
/// Gets the version of the mod.
/// </summary>
public string Version { get; }
/// <summary>
/// Gets the flags of the mod.
/// </summary>
public ModFlags Flags { get; }
/// <summary>
/// Gets the name of the mod.
/// </summary>
public string? Name { get; }
/// <summary>
/// Gets a value indicating whether the mod is required on all clients.
/// </summary>
public bool IsRequiredOnAllClients => (Flags & ModFlags.RequireOnAllClients) != 0;
/// <inheritdoc />
public bool Equals(Mod other)
{
return Id == other.Id && Version == other.Version;
}
/// <inheritdoc />
public override bool Equals(object? obj)
{
return obj is Mod other && Equals(other);
}
/// <inheritdoc />
public static bool operator ==(Mod left, Mod right)
{
return left.Equals(right);
}
/// <inheritdoc />
public static bool operator !=(Mod left, Mod right)
{
return !(left == right);
}
/// <inheritdoc />
public override int GetHashCode()
{
return HashCode.Combine(Id, Version);
}
/// <inheritdoc />
public override string ToString()
{
return $"{Name ?? Id} ({Version})";
}
internal static bool Validate(IReadOnlyCollection<Mod> clientMods, IReadOnlyCollection<Mod> hostMods, [NotNullWhen(false)] out string? reason)
{
var clientMissing = hostMods.Where(mod => mod.IsRequiredOnAllClients && !clientMods.Contains(mod)).ToArray();
var hostMissing = clientMods.Where(mod => mod.IsRequiredOnAllClients && !hostMods.Contains(mod)).ToArray();
if (clientMissing.Any() || hostMissing.Any())
{
var message = new StringBuilder();
if (clientMissing.Any())
{
message.Append("You are missing: ");
message.AppendJoin(", ", clientMissing.Select(x => x.ToString()));
message.AppendLine();
}
if (hostMissing.Any())
{
message.Append("Host is missing: ");
message.AppendJoin(", ", hostMissing.Select(x => x.ToString()));
message.AppendLine();
}
reason = message.ToString();
return false;
}
reason = null;
return true;
}
}
+30
View File
@@ -0,0 +1,30 @@
using System;
namespace Reactor.Networking;
/// <summary>
/// Represents flags of the mod.
/// </summary>
[Flags]
public enum ModFlags : ushort
{
/// <summary>
/// No flags.
/// </summary>
None = 0,
/// <summary>
/// Requires all clients in a lobby to have the mod.
/// </summary>
RequireOnAllClients = 1 << 0,
/// <summary>
/// Requires the server to have a plugin that handles the mod.
/// </summary>
RequireOnServer = 1 << 1,
/// <summary>
/// Requires the host of the lobby to have the mod.
/// </summary>
RequireOnHost = 1 << 2,
}
@@ -0,0 +1,35 @@
<Project>
<Import Project="Sdk.props" Sdk="Microsoft.NET.Sdk" />
<PropertyGroup>
<TargetFramework>net6.0</TargetFramework>
<RootNamespace>Reactor.Networking</RootNamespace>
<Description>Shared sources for Reactor.Networking (Reactor and Reactor.Impostor)</Description>
<ContentTargetFolders>contentFiles</ContentTargetFolders>
<IsPackable>true</IsPackable>
<IncludeBuildOutput>false</IncludeBuildOutput>
<GenerateAssemblyInfo>false</GenerateAssemblyInfo>
<GenerateTargetFrameworkAttribute>false</GenerateTargetFrameworkAttribute>
<NoBuild>true</NoBuild>
<GeneratePackageOnBuild>true</GeneratePackageOnBuild>
<SuppressDependenciesWhenPacking>true</SuppressDependenciesWhenPacking>
<GenerateDocumentationFile>true</GenerateDocumentationFile>
</PropertyGroup>
<ItemGroup>
<Compile Update="@(Compile)">
<Pack>true</Pack>
<PackagePath>$(ContentTargetFolders)\cs\any\$(PackageId)\%(RecursiveDir)\</PackagePath>
</Compile>
</ItemGroup>
<ItemGroup>
<PackageReference Remove="@(PackageReference)" />
</ItemGroup>
<Import Project="Sdk.targets" Sdk="Microsoft.NET.Sdk" />
<Target Name="CopyFilesToOutputDirectory" />
</Project>
@@ -0,0 +1,12 @@
namespace Reactor.Networking;
/// <summary>
/// Represents a GameData flag for Reactor messages.
/// </summary>
public enum ReactorGameDataFlag : byte
{
/// <summary>
/// KickWithReason GameData message.
/// </summary>
SetKickReason,
}
@@ -0,0 +1,12 @@
namespace Reactor.Networking;
/// <summary>
/// Represents a message flag for Reactor messages.
/// </summary>
public enum ReactorMessageFlags : byte
{
/// <summary>
/// Handshake message.
/// </summary>
Handshake,
}
@@ -0,0 +1,22 @@
namespace Reactor.Networking;
/// <summary>
/// Version of the Reactor.Networking protocol format.
/// </summary>
public enum ReactorProtocolVersion : byte
{
/// <summary>
/// First public Reactor Protocol version.
/// </summary>
V2 = 1,
/// <summary>
/// Version introducing vanilla server support, syncer concept and registries.
/// </summary>
V3 = 2,
/// <summary>
/// Latest version.
/// </summary>
Latest = V3,
}
@@ -0,0 +1,6 @@
{
"version": 1,
"dependencies": {
"net6.0": {}
}
}
-40
View File
@@ -1,40 +0,0 @@
#nullable enable
using System;
namespace Reactor.Networking
{
public class Mod
{
public Mod(uint netId, string id, string version, PluginSide side)
{
NetId = netId;
Id = id;
Version = version;
Side = side;
}
public uint NetId { get; }
public string Id { get; }
public string Version { get; }
public PluginSide Side { get; }
protected bool Equals(Mod other)
{
return Id == other.Id && Version == other.Version;
}
public override bool Equals(object? obj)
{
if (ReferenceEquals(null, obj)) return false;
if (ReferenceEquals(this, obj)) return true;
if (obj.GetType() != GetType()) return false;
return Equals((Mod) obj);
}
public override int GetHashCode()
{
return HashCode.Combine(Id, Version);
}
}
}
@@ -1,9 +0,0 @@
namespace Reactor.Networking
{
public enum ReactorMessageFlags : byte
{
Handshake,
ModDeclaration,
PluginDeclaration
}
}
@@ -1,18 +0,0 @@
namespace Reactor.Networking
{
/// <summary>
/// Version of the Reactor.Net protocol format.
/// </summary>
public enum ReactorProtocolVersion : byte
{
/// <summary>
/// Initial version.
/// </summary>
Initial = 1,
/// <summary>
/// Latest version.
/// </summary>
Latest = Initial,
}
}
-18
View File
@@ -1,18 +0,0 @@
namespace Reactor
{
/// <summary>
/// Plugin side used in modded handshake
/// </summary>
public enum PluginSide : byte
{
/// <summary>
/// Required by both sides, reject connection if missing on the other side
/// </summary>
Both,
/// <summary>
/// Required only by client
/// </summary>
ClientOnly
}
}
-5
View File
@@ -1,5 +0,0 @@
<Project>
<ItemGroup>
<Compile Include="$(MSBuildThisFileDirectory)**\*.cs" />
</ItemGroup>
</Project>
-3
View File
@@ -1,3 +0,0 @@
<Project>
<Import Project="Reactor.Shared.projitems" Label="Shared" />
</Project>
+20 -1
View File
@@ -5,7 +5,18 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Reactor.Debugger", "Reactor
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Reactor.Example", "Reactor.Example\Reactor.Example.csproj", "{26A83466-26FE-4383-A35C-B8629902F909}"
EndProject
Project("{D954291E-2A0B-460D-934E-DC6B0785DB48}") = "Reactor.Shared", "Reactor.Shared\Reactor.Shared.shproj", "{8C1EEFE9-EF8A-47C4-810E-6D9BA1E7218B}"
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Reactor.Benchmarks", "Reactor.Benchmarks\Reactor.Benchmarks.csproj", "{99B87307-3AEB-4A6A-BF45-871768308FDD}"
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Files", "Solution Files", "{4BBF0A80-F6E6-4FDD-ADD0-8CB4F28F88A4}"
ProjectSection(SolutionItems) = preProject
AmongUs.props = AmongUs.props
Directory.Build.props = Directory.Build.props
nuget.config = nuget.config
stylecop.json = stylecop.json
stylecop.ruleset = stylecop.ruleset
EndProjectSection
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Reactor.Networking.Shared", "Reactor.Networking.Shared\Reactor.Networking.Shared.csproj", "{1E68CA20-22EB-4E57-B525-81970BE6363D}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
@@ -25,6 +36,14 @@ Global
{26A83466-26FE-4383-A35C-B8629902F909}.Debug|Any CPU.Build.0 = Debug|Any CPU
{26A83466-26FE-4383-A35C-B8629902F909}.Release|Any CPU.ActiveCfg = Release|Any CPU
{26A83466-26FE-4383-A35C-B8629902F909}.Release|Any CPU.Build.0 = Release|Any CPU
{99B87307-3AEB-4A6A-BF45-871768308FDD}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{99B87307-3AEB-4A6A-BF45-871768308FDD}.Debug|Any CPU.Build.0 = Debug|Any CPU
{99B87307-3AEB-4A6A-BF45-871768308FDD}.Release|Any CPU.ActiveCfg = Release|Any CPU
{99B87307-3AEB-4A6A-BF45-871768308FDD}.Release|Any CPU.Build.0 = Release|Any CPU
{1E68CA20-22EB-4E57-B525-81970BE6363D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{1E68CA20-22EB-4E57-B525-81970BE6363D}.Debug|Any CPU.Build.0 = Debug|Any CPU
{1E68CA20-22EB-4E57-B525-81970BE6363D}.Release|Any CPU.ActiveCfg = Release|Any CPU
{1E68CA20-22EB-4E57-B525-81970BE6363D}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(NestedProjects) = preSolution
EndGlobalSection
Binary file not shown.
Binary file not shown.
Binary file not shown.
-34
View File
@@ -1,34 +0,0 @@
using System.Collections.Generic;
using System.Reflection.Emit;
using BepInEx.IL2CPP;
using HarmonyLib;
namespace Reactor
{
public static class ChainloaderHooks
{
public delegate void PluginLoadHandler(BasePlugin plugin);
public static event PluginLoadHandler PluginLoad;
internal static void OnPluginLoad(BasePlugin plugin)
{
PluginLoad?.Invoke(plugin);
}
[HarmonyPatch(typeof(IL2CPPChainloader), nameof(IL2CPPChainloader.LoadPlugin))]
private static class LoadPluginPatch
{
public static IEnumerable<CodeInstruction> Transpiler(IEnumerable<CodeInstruction> instructions)
{
return new CodeMatcher(instructions)
.MatchForward(false, new CodeMatch(OpCodes.Callvirt, AccessTools.Method(typeof(BasePlugin), nameof(BasePlugin.Load))))
.Insert(
new CodeInstruction(OpCodes.Dup),
new CodeInstruction(OpCodes.Call, AccessTools.Method(typeof(ChainloaderHooks), nameof(OnPluginLoad)))
)
.InstructionEnumeration();
}
}
}
}
+13
View File
@@ -0,0 +1,13 @@
// ReSharper disable CheckNamespace
namespace System.Runtime.CompilerServices;
/// <summary>
/// This attribute is required by the compiler for the "unmanaged" generic type constraint.
/// It should be generated automatically, but for whatever reason its not.
/// </summary>
[Obsolete("Do not use directly.", true)]
[AttributeUsage(AttributeTargets.All)]
internal sealed class IsUnmanagedAttribute : Attribute
{
}
-385
View File
@@ -1,385 +0,0 @@
// Adapted from https://github.com/LavaGang/MelonLoader/blob/364515defde1d781daf39c10331f883254295774/SM_Il2Cpp/Coroutines.cs#L10
/*
Apache License
Version 2.0, January 2004
http://www.apache.org/licenses/
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
1. Definitions.
"License" shall mean the terms and conditions for use, reproduction,
and distribution as defined by Sections 1 through 9 of this document.
"Licensor" shall mean the copyright owner or entity authorized by
the copyright owner that is granting the License.
"Legal Entity" shall mean the union of the acting entity and all
other entities that control, are controlled by, or are under common
control with that entity. For the purposes of this definition,
"control" means (i) the power, direct or indirect, to cause the
direction or management of such entity, whether by contract or
otherwise, or (ii) ownership of fifty percent (50%) or more of the
outstanding shares, or (iii) beneficial ownership of such entity.
"You" (or "Your") shall mean an individual or Legal Entity
exercising permissions granted by this License.
"Source" form shall mean the preferred form for making modifications,
including but not limited to software source code, documentation
source, and configuration files.
"Object" form shall mean any form resulting from mechanical
transformation or translation of a Source form, including but
not limited to compiled object code, generated documentation,
and conversions to other media types.
"Work" shall mean the work of authorship, whether in Source or
Object form, made available under the License, as indicated by a
copyright notice that is included in or attached to the work
(an example is provided in the Appendix below).
"Derivative Works" shall mean any work, whether in Source or Object
form, that is based on (or derived from) the Work and for which the
editorial revisions, annotations, elaborations, or other modifications
represent, as a whole, an original work of authorship. For the purposes
of this License, Derivative Works shall not include works that remain
separable from, or merely link (or bind by name) to the interfaces of,
the Work and Derivative Works thereof.
"Contribution" shall mean any work of authorship, including
the original version of the Work and any modifications or additions
to that Work or Derivative Works thereof, that is intentionally
submitted to Licensor for inclusion in the Work by the copyright owner
or by an individual or Legal Entity authorized to submit on behalf of
the copyright owner. For the purposes of this definition, "submitted"
means any form of electronic, verbal, or written communication sent
to the Licensor or its representatives, including but not limited to
communication on electronic mailing lists, source code control systems,
and issue tracking systems that are managed by, or on behalf of, the
Licensor for the purpose of discussing and improving the Work, but
excluding communication that is conspicuously marked or otherwise
designated in writing by the copyright owner as "Not a Contribution."
"Contributor" shall mean Licensor and any individual or Legal Entity
on behalf of whom a Contribution has been received by Licensor and
subsequently incorporated within the Work.
2. Grant of Copyright License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
copyright license to reproduce, prepare Derivative Works of,
publicly display, publicly perform, sublicense, and distribute the
Work and such Derivative Works in Source or Object form.
3. Grant of Patent License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
(except as stated in this section) patent license to make, have made,
use, offer to sell, sell, import, and otherwise transfer the Work,
where such license applies only to those patent claims licensable
by such Contributor that are necessarily infringed by their
Contribution(s) alone or by combination of their Contribution(s)
with the Work to which such Contribution(s) was submitted. If You
institute patent litigation against any entity (including a
cross-claim or counterclaim in a lawsuit) alleging that the Work
or a Contribution incorporated within the Work constitutes direct
or contributory patent infringement, then any patent licenses
granted to You under this License for that Work shall terminate
as of the date such litigation is filed.
4. Redistribution. You may reproduce and distribute copies of the
Work or Derivative Works thereof in any medium, with or without
modifications, and in Source or Object form, provided that You
meet the following conditions:
(a) You must give any other recipients of the Work or
Derivative Works a copy of this License; and
(b) You must cause any modified files to carry prominent notices
stating that You changed the files; and
(c) You must retain, in the Source form of any Derivative Works
that You distribute, all copyright, patent, trademark, and
attribution notices from the Source form of the Work,
excluding those notices that do not pertain to any part of
the Derivative Works; and
(d) If the Work includes a "NOTICE" text file as part of its
distribution, then any Derivative Works that You distribute must
include a readable copy of the attribution notices contained
within such NOTICE file, excluding those notices that do not
pertain to any part of the Derivative Works, in at least one
of the following places: within a NOTICE text file distributed
as part of the Derivative Works; within the Source form or
documentation, if provided along with the Derivative Works; or,
within a display generated by the Derivative Works, if and
wherever such third-party notices normally appear. The contents
of the NOTICE file are for informational purposes only and
do not modify the License. You may add Your own attribution
notices within Derivative Works that You distribute, alongside
or as an addendum to the NOTICE text from the Work, provided
that such additional attribution notices cannot be construed
as modifying the License.
You may add Your own copyright statement to Your modifications and
may provide additional or different license terms and conditions
for use, reproduction, or distribution of Your modifications, or
for any such Derivative Works as a whole, provided Your use,
reproduction, and distribution of the Work otherwise complies with
the conditions stated in this License.
5. Submission of Contributions. Unless You explicitly state otherwise,
any Contribution intentionally submitted for inclusion in the Work
by You to the Licensor shall be under the terms and conditions of
this License, without any additional terms or conditions.
Notwithstanding the above, nothing herein shall supersede or modify
the terms of any separate license agreement you may have executed
with Licensor regarding such Contributions.
6. Trademarks. This License does not grant permission to use the trade
names, trademarks, service marks, or product names of the Licensor,
except as required for reasonable and customary use in describing the
origin of the Work and reproducing the content of the NOTICE file.
7. Disclaimer of Warranty. Unless required by applicable law or
agreed to in writing, Licensor provides the Work (and each
Contributor provides its Contributions) on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
implied, including, without limitation, any warranties or conditions
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
PARTICULAR PURPOSE. You are solely responsible for determining the
appropriateness of using or redistributing the Work and assume any
risks associated with Your exercise of permissions under this License.
8. Limitation of Liability. In no event and under no legal theory,
whether in tort (including negligence), contract, or otherwise,
unless required by applicable law (such as deliberate and grossly
negligent acts) or agreed to in writing, shall any Contributor be
liable to You for damages, including any direct, indirect, special,
incidental, or consequential damages of any character arising as a
result of this License or out of the use or inability to use the
Work (including but not limited to damages for loss of goodwill,
work stoppage, computer failure or malfunction, or any and all
other commercial damages or losses), even if such Contributor
has been advised of the possibility of such damages.
9. Accepting Warranty or Additional Liability. While redistributing
the Work or Derivative Works thereof, You may choose to offer,
and charge a fee for, acceptance of support, warranty, indemnity,
or other liability obligations and/or rights consistent with this
License. However, in accepting such obligations, You may act only
on Your own behalf and on Your sole responsibility, not on behalf
of any other Contributor, and only if You agree to indemnify,
defend, and hold each Contributor harmless for any liability
incurred by, or claims asserted against, such Contributor by reason
of your accepting any such warranty or additional liability.
END OF TERMS AND CONDITIONS
Copyright 2020 Lava Gang
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using UnhollowerBaseLib;
using UnityEngine;
namespace Reactor
{
public class Il2CppEnumeratorWrapper : IEnumerator
{
private readonly Il2CppSystem.Collections.IEnumerator _il2CPPEnumerator;
public Il2CppEnumeratorWrapper(Il2CppSystem.Collections.IEnumerator il2CppEnumerator) => _il2CPPEnumerator = il2CppEnumerator;
public bool MoveNext() => _il2CPPEnumerator.MoveNext();
public void Reset() => _il2CPPEnumerator.Reset();
public object Current => _il2CPPEnumerator.Current;
}
public static class Coroutines
{
private struct CoroutineTuple
{
public object WaitCondition;
public IEnumerator Coroutine;
}
[RegisterInIl2Cpp]
internal class Component : MonoBehaviour
{
public Component(IntPtr ptr) : base(ptr)
{
}
private void Start()
{
Camera.onPostRender = Camera.onPostRender == null
? new Action<Camera>(OnPostRenderM)
: Il2CppSystem.Delegate.Combine(Camera.onPostRender, (Camera.CameraCallback) (Action<Camera>) OnPostRenderM).Cast<Camera.CameraCallback>();
}
private void FixedUpdate()
{
ProcessCoroutineList(_ourWaitForFixedUpdateCoroutines);
}
private void Update()
{
Process();
}
public static Camera OnPostRenderCam { get; private set; }
private static void OnPostRenderM(Camera camera)
{
if (OnPostRenderCam == null)
{
OnPostRenderCam = camera;
}
if (OnPostRenderCam == camera)
{
ProcessCoroutineList(_ourWaitForEndOfFrameCoroutines);
}
}
}
private static readonly List<CoroutineTuple> _ourCoroutinesStore = new List<CoroutineTuple>();
private static readonly List<IEnumerator> _ourNextFrameCoroutines = new List<IEnumerator>();
private static readonly List<IEnumerator> _ourWaitForFixedUpdateCoroutines = new List<IEnumerator>();
private static readonly List<IEnumerator> _ourWaitForEndOfFrameCoroutines = new List<IEnumerator>();
private static readonly List<IEnumerator> _tempList = new List<IEnumerator>();
public static IEnumerator Start(IEnumerator routine)
{
if (routine != null) ProcessNextOfCoroutine(routine);
return routine;
}
public static void Stop(IEnumerator enumerator)
{
if (_ourNextFrameCoroutines.Contains(enumerator)) // the coroutine is running itself
{
_ourNextFrameCoroutines.Remove(enumerator);
}
else
{
var coroutineTupleIndex = _ourCoroutinesStore.FindIndex(c => c.Coroutine == enumerator);
if (coroutineTupleIndex != -1) // the coroutine is waiting for a subroutine
{
var waitCondition = _ourCoroutinesStore[coroutineTupleIndex].WaitCondition;
if (waitCondition is IEnumerator waitEnumerator)
{
Stop(waitEnumerator);
}
_ourCoroutinesStore.RemoveAt(coroutineTupleIndex);
}
}
}
private static void ProcessCoroutineList(List<IEnumerator> target)
{
if (target.Count == 0) return;
// use a temp list to make sure waits made during processing are not handled by same processing invocation
// additionally, a temp list reduces allocations compared to an array
_tempList.AddRange(target);
target.Clear();
foreach (var enumerator in _tempList) ProcessNextOfCoroutine(enumerator);
_tempList.Clear();
}
private static void Process()
{
for (var i = _ourCoroutinesStore.Count - 1; i >= 0; i--)
{
var tuple = _ourCoroutinesStore[i];
if (tuple.WaitCondition is WaitForSeconds waitForSeconds)
{
if ((waitForSeconds.m_Seconds -= Time.deltaTime) <= 0)
{
_ourCoroutinesStore.RemoveAt(i);
ProcessNextOfCoroutine(tuple.Coroutine);
}
}
}
ProcessCoroutineList(_ourNextFrameCoroutines);
}
private static void ProcessNextOfCoroutine(IEnumerator enumerator)
{
try
{
if (!enumerator.MoveNext()) // Run the next step of the coroutine. If it's done, restore the parent routine
{
var indices = _ourCoroutinesStore.Select((it, idx) => (idx, it)).Where(it => it.it.WaitCondition == enumerator).Select(it => it.idx).ToList();
for (var i = indices.Count - 1; i >= 0; i--)
{
var index = indices[i];
_ourNextFrameCoroutines.Add(_ourCoroutinesStore[index].Coroutine);
_ourCoroutinesStore.RemoveAt(index);
}
return;
}
}
catch (Exception e)
{
Logger<ReactorPlugin>.Error(e.ToString());
Stop(FindOriginalCoroutine(enumerator)); // We want the entire coroutine hierarchy to stop when an error happen
}
var next = enumerator.Current;
switch (next)
{
case null:
_ourNextFrameCoroutines.Add(enumerator);
return;
case WaitForFixedUpdate _:
_ourWaitForFixedUpdateCoroutines.Add(enumerator);
return;
case WaitForEndOfFrame _:
_ourWaitForEndOfFrameCoroutines.Add(enumerator);
return;
case WaitForSeconds _:
break; // do nothing, this one is supported in Process
case Il2CppObjectBase il2CppObjectBase:
var nextAsEnumerator = il2CppObjectBase.TryCast<Il2CppSystem.Collections.IEnumerator>();
if (nextAsEnumerator != null) // il2cpp IEnumerator also handles CustomYieldInstruction
next = new Il2CppEnumeratorWrapper(nextAsEnumerator);
else
Logger<ReactorPlugin>.Warning($"Unknown coroutine yield object of type {il2CppObjectBase} for coroutine {enumerator}");
break;
}
_ourCoroutinesStore.Add(new CoroutineTuple { WaitCondition = next, Coroutine = enumerator });
if (next is IEnumerator nextCoroutine)
ProcessNextOfCoroutine(nextCoroutine);
}
private static IEnumerator FindOriginalCoroutine(IEnumerator enumerator)
{
var index = _ourCoroutinesStore.FindIndex(ct => ct.WaitCondition == enumerator);
return index == -1 ? enumerator : FindOriginalCoroutine(_ourCoroutinesStore[index].Coroutine);
}
}
}
-71
View File
@@ -1,71 +0,0 @@
using System.Collections.Generic;
using System.Linq;
using HarmonyLib;
using UnhollowerBaseLib;
namespace Reactor
{
public class CustomStringName
{
private static int _lastId = -1;
private static readonly List<CustomStringName> _list = new List<CustomStringName>();
public static IReadOnlyList<CustomStringName> List => _list.AsReadOnly();
public static CustomStringName Register(string value)
{
var customStringName = new CustomStringName(_lastId--, value);
_list.Add(customStringName);
return customStringName;
}
public int Id { get; }
public string Value { get; }
private CustomStringName(int id, string value)
{
Id = id;
Value = value;
}
public static implicit operator StringNames(CustomStringName name) => (StringNames) name.Id;
public static explicit operator CustomStringName(StringNames name) => List.SingleOrDefault(x => x.Id == (int) name);
[HarmonyPatch(typeof(TranslationController), nameof(TranslationController.GetString), typeof(StringNames), typeof(Il2CppReferenceArray<Il2CppSystem.Object>))]
private static class GetStringPatch
{
public static bool Prefix([HarmonyArgument(0)] StringNames stringId, [HarmonyArgument(1)] Il2CppReferenceArray<Il2CppSystem.Object> parts, ref string __result)
{
var customStringName = (CustomStringName) stringId;
if (customStringName != null)
{
__result = string.Format(customStringName.Value, parts);
return false;
}
return true;
}
}
[HarmonyPatch(typeof(TranslationController), nameof(TranslationController.GetStringWithDefault))]
private static class GetStringOrDefaultPatch
{
public static bool Prefix([HarmonyArgument(0)] StringNames stringId, [HarmonyArgument(2)] Il2CppReferenceArray<Il2CppSystem.Object> parts, ref string __result)
{
var customStringName = (CustomStringName) stringId;
if (customStringName != null)
{
__result = string.Format(customStringName.Value, parts);
return false;
}
return true;
}
}
}
}
-123
View File
@@ -1,123 +0,0 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Threading.Tasks;
using HarmonyLib;
using UnityEngine;
using UnityEngine.Events;
using UnityEngine.Networking;
using UnityEngine.SceneManagement;
using Il2CppType = UnhollowerRuntimeLib.Il2CppType;
namespace Reactor.Extensions
{
/// <summary>
/// General utilities
/// </summary>
public static class Extensions
{
/// <summary>
/// Adds a delegate to get one notification when a scene has loaded.
/// </summary>
public static void once_sceneLoaded(Action<Scene, LoadSceneMode> value)
{
UnityAction<Scene, LoadSceneMode> unityAction = null;
unityAction = (Action<Scene, LoadSceneMode>) ((scene, loadMode) =>
{
SceneManager.remove_sceneLoaded(unityAction);
value.Invoke(scene, loadMode);
});
SceneManager.add_sceneLoaded(unityAction);
}
/// <summary>
/// Returns random <typeparamref name="T"/> from <paramref name="input"/>
/// </summary>
public static T Random<T>(this IEnumerable<T> input)
{
var list = input as IList<T> ?? input.ToList();
return list.Count == 0 ? default : list[UnityEngine.Random.Range(0, list.Count)];
}
/// <summary>
/// Returns the color as a hexadecimal string in the format "RRGGBBAA".
/// </summary>
/// <param name="color">The color to be converted.</param>
/// <returns>Hexadecimal string representing the color.</returns>
/// <remarks>https://docs.unity3d.com/ScriptReference/ColorUtility.ToHtmlStringRGBA.html</remarks>
public static string ToHtmlStringRGBA(this Color32 color)
{
return $"{color.r:X2}{color.g:X2}{color.b:X2}{color.a:X2}";
}
/// <inheritdoc cref="ToHtmlStringRGBA(UnityEngine.Color32)"/>
public static string ToHtmlStringRGBA(this Color color)
{
return ((Color32) color).ToHtmlStringRGBA();
}
/// <summary>
/// Fully read <paramref name="input"/> stream, can be used as workaround for il2cpp streams.
/// </summary>
public static byte[] ReadFully(this Stream input)
{
using (var ms = new MemoryStream())
{
input.CopyTo(ms);
return ms.ToArray();
}
}
/// <summary>
/// Sends <see cref="UnityWebRequest"/> and return task that finishes on <paramref name="request"/> completion.
/// </summary>
public static Task SendAsync(this UnityWebRequest request)
{
var task = new TaskCompletionSource<object>();
request.Send().m_completeCallback = (Action<AsyncOperation>) (x =>
{
task.SetResult(null);
});
return task.Task;
}
private static readonly int _outline = Shader.PropertyToID("_Outline");
private static readonly int _outlineColor = Shader.PropertyToID("_OutlineColor");
private static readonly int _addColor = Shader.PropertyToID("_AddColor");
/// <summary>
/// Sets color outline for renderers using default Among Us shader
/// </summary>
public static void SetOutline(this Renderer renderer, Color? color)
{
renderer.material.SetFloat(_outline, color.HasValue ? 1 : 0);
if (color.HasValue)
{
renderer.material.SetColor(_outlineColor, color.Value);
renderer.material.SetColor(_addColor, color.Value);
}
}
public static IEnumerable<MethodBase> GetMethods(this Type type, BindingFlags bindingAttr, Type returnType, params Type[] parameterTypes)
{
return type.GetMethods(bindingAttr).Where(x => x.ReturnType == returnType && x.GetParameters().Select(x => x.ParameterType).SequenceEqual(parameterTypes));
}
public static IEnumerable<MethodBase> GetMethods(this Type type, Type returnType, params Type[] parameterTypes)
{
return type.GetMethods(AccessTools.all, returnType, parameterTypes);
}
public static T LoadAsset<T>(this AssetBundle assetBundle, string name) where T : UnityEngine.Object
{
return assetBundle.LoadAsset(name, Il2CppType.Of<T>())?.Cast<T>();
}
}
}
@@ -1,50 +0,0 @@
using System;
using Hazel;
using Hazel.Udp;
using UnityEngine;
namespace Reactor.Extensions
{
public static class ExtraMessageExtensions
{
private const float MIN = -50f;
private const float MAX = 50f;
private static float ReverseLerp(float t)
{
return Mathf.Clamp((t - MIN) / (MAX - MIN), 0f, 1f);
}
public static void Write(this MessageWriter writer, Vector2 value)
{
var x = (ushort) (ReverseLerp(value.x) * ushort.MaxValue);
var y = (ushort) (ReverseLerp(value.y) * ushort.MaxValue);
writer.Write(x);
writer.Write(y);
}
public static Vector2 ReadVector2(this MessageReader reader)
{
var x = reader.ReadUInt16() / (float) ushort.MaxValue;
var y = reader.ReadUInt16() / (float) ushort.MaxValue;
return new Vector2(Mathf.Lerp(MIN, MAX, x), Mathf.Lerp(MIN, MAX, y));
}
public static void Send(this UdpConnection connection, MessageWriter msg, Action ackCallback)
{
if (msg.SendOption != SendOption.Reliable)
throw new InvalidOperationException("Message SendOption has to be Reliable.");
var buffer = new byte[msg.Length];
Buffer.BlockCopy(msg.Buffer, 0, buffer, 0, msg.Length);
connection.ResetKeepAliveTimer();
connection.AttachReliableID(buffer, 1, ackCallback);
connection.WriteBytesToConnection(buffer, buffer.Length);
connection.Statistics.LogReliableSend(buffer.Length - 3, buffer.Length);
}
}
}
-145
View File
@@ -1,145 +0,0 @@
using System;
using UnhollowerBaseLib;
using UnityEngine;
using UnityEngine.EventSystems;
using UnityEngine.UI;
namespace Reactor.Extensions
{
/// <summary>
/// GUI utilities
/// </summary>
public static class GUIExtensions
{
/// <summary>
/// Shortcut for empty texture
/// </summary>
public static Texture2D CreateEmptyTexture(int width = 0, int height = 0)
{
return new Texture2D(width, height, TextureFormat.RGBA32, Texture.GenerateAllMips, false, IntPtr.Zero);
}
/// <summary>
/// Clamp Rect to screen size
/// </summary>
public static Rect ClampScreen(this Rect rect)
{
rect.x = Mathf.Clamp(rect.x, 0, Screen.width - rect.width);
rect.y = Mathf.Clamp(rect.y, 0, Screen.height - rect.height);
return rect;
}
/// <summary>
/// Reset Rect size
/// </summary>
public static Rect ResetSize(this Rect rect)
{
rect.width = rect.height = 0;
return rect;
}
/// <summary>
/// Create <see cref="Sprite"/> from <paramref name="tex"/>
/// </summary>
public static Sprite CreateSprite(this Texture2D tex)
{
return Sprite.Create(tex, new Rect(0, 0, tex.width, tex.height), new Vector2(0.5f, 0.5f), 100f);
}
public static DefaultControls.Resources StandardResources { get; internal set; }
public static GameObject CreateCanvas()
{
var gameObject = new GameObject("Canvas");
var canvas = gameObject.AddComponent<Canvas>();
canvas.renderMode = RenderMode.ScreenSpaceOverlay;
var canvasScaler = gameObject.AddComponent<CanvasScaler>();
canvasScaler.screenMatchMode = CanvasScaler.ScreenMatchMode.Expand;
canvasScaler.referencePixelsPerUnit = 100f;
gameObject.AddComponent<GraphicRaycaster>();
return gameObject;
}
public static GameObject CreateEventSystem()
{
var gameObject = new GameObject("EventSystem");
gameObject.AddComponent<EventSystem>();
gameObject.AddComponent<StandaloneInputModule>();
gameObject.AddComponent<BaseInput>();
return gameObject;
}
public static void SetSize(this RectTransform rectTransform, float width, float height)
{
rectTransform.SetSizeWithCurrentAnchors(RectTransform.Axis.Horizontal, width);
rectTransform.SetSizeWithCurrentAnchors(RectTransform.Axis.Vertical, height);
}
}
public class Window
{
private static int _lastWindowId;
public static int NextWindowId()
{
return _lastWindowId++;
}
public int Id { get; set; } = NextWindowId();
public bool Enabled { get; set; } = true;
public Rect Rect { get; set; }
public Action<int> Func { get; set; }
public string Title { get; set; }
public Window(Rect rect, string title, Action<int> func)
{
Rect = rect;
Title = title;
Func = func;
}
public Window(Rect rect, string title, Action func) : this(rect, title, id => func())
{
}
public void OnGUI()
{
if (Enabled)
{
Rect = Rect.ResetSize();
Rect = GUILayout.Window(Id, Rect, Func, Title, new Il2CppReferenceArray<GUILayoutOption>(0));
if ((Input.GetMouseButtonDown(0) || Input.GetMouseButtonDown(1)) && Rect.Contains(new Vector2(Input.mousePosition.x, Screen.height - Input.mousePosition.y)))
{
Input.ResetInputAxes();
}
}
}
}
public class DragWindow : Window
{
public DragWindow(Rect rect, string title, Action<int> func) : base(rect, title, func)
{
Func = id =>
{
func(id);
GUI.DragWindow(new Rect(0, 0, 10000, 20));
Rect = Rect.ClampScreen();
};
}
public DragWindow(Rect rect, string title, Action func) : this(rect, title, id => func())
{
}
}
}
@@ -1,17 +0,0 @@
using UnityEngine;
namespace Reactor.Extensions
{
public static class PlayerControlExtensions
{
public static Color32 ToPlayerColor(this PlayerColor color)
{
return Palette.PlayerColors[(byte) color];
}
public static Color32 ToShadowColor(this PlayerColor color)
{
return Palette.ShadowColors[(byte) color];
}
}
}
@@ -1,43 +0,0 @@
using UnityEngine;
namespace Reactor.Extensions
{
public static class UnityObjectExtensions
{
/// <summary>
/// Stops <paramref name="obj"/> from being destroyed
/// </summary>
/// <param name="obj">Object to stop from being destroyed</param>
/// <returns>Passed <paramref name="obj"/></returns>
public static T DontDestroy<T>(this T obj) where T : Object
{
obj.hideFlags |= HideFlags.HideAndDontSave;
return obj.DontDestroyOnLoad();
}
public static T DontUnload<T>(this T obj) where T : Object
{
obj.hideFlags |= HideFlags.DontUnloadUnusedAsset;
return obj;
}
public static T DontDestroyOnLoad<T>(this T obj) where T : Object
{
Object.DontDestroyOnLoad(obj);
return obj;
}
public static void Destroy(this Object obj)
{
Object.Destroy(obj);
}
public static void DestroyImmediate(this Object obj)
{
Object.DestroyImmediate(obj);
}
}
}
-38
View File
@@ -1,38 +0,0 @@
using System.Collections.Generic;
using Il2CppSystem.Runtime.CompilerServices;
namespace Reactor
{
public sealed class Il2CppEqualityComparer<T> : IEqualityComparer<T> where T : Il2CppSystem.Object
{
private static Il2CppEqualityComparer<T> _instance;
public static Il2CppEqualityComparer<T> Instance
{
get
{
_instance ??= new Il2CppEqualityComparer<T>();
return _instance;
}
}
private Il2CppEqualityComparer()
{
}
public int GetHashCode(T value)
{
return RuntimeHelpers.GetHashCode(value);
}
public bool Equals(T left, T right)
{
if (left == null || right == null)
{
return left == null && right == null;
}
return left.Equals(right);
}
}
}
-11
View File
@@ -1,11 +0,0 @@
// https://stackoverflow.com/questions/64749385/predefined-type-system-runtime-compilerservices-isexternalinit-is-not-defined?noredirect=1&lq=1
// IsExternalInit is not included with netstandard2.1 even tho it could
// ReSharper disable CheckNamespace
namespace System.Runtime.CompilerServices
{
public static class IsExternalInit
{
}
}
@@ -0,0 +1,39 @@
using System;
using System.Globalization;
namespace Reactor.Localization.Extensions;
/// <summary>
/// Provides extension methods for <see cref="SupportedLangs"/>.
/// </summary>
public static class SupportedLangsExtensions
{
/// <summary>
/// Gets a <see cref="CultureInfo"/> from the specified <paramref name="language"/>.
/// </summary>
/// <param name="language">The <see cref="SupportedLangs"/>.</param>
/// <returns>a <see cref="CultureInfo"/>.</returns>
public static CultureInfo ToCultureInfo(this SupportedLangs language)
{
return language switch
{
SupportedLangs.English => CultureInfo.GetCultureInfo("en"),
SupportedLangs.Latam => CultureInfo.GetCultureInfo("es"),
SupportedLangs.Brazilian => CultureInfo.GetCultureInfo("pt-BR"),
SupportedLangs.Portuguese => CultureInfo.GetCultureInfo("pt"),
SupportedLangs.Korean => CultureInfo.GetCultureInfo("ko"),
SupportedLangs.Russian => CultureInfo.GetCultureInfo("ru"),
SupportedLangs.Dutch => CultureInfo.GetCultureInfo("nl"),
SupportedLangs.Filipino => CultureInfo.GetCultureInfo("fil"),
SupportedLangs.French => CultureInfo.GetCultureInfo("fr"),
SupportedLangs.German => CultureInfo.GetCultureInfo("de"),
SupportedLangs.Italian => CultureInfo.GetCultureInfo("it"),
SupportedLangs.Japanese => CultureInfo.GetCultureInfo("ja"),
SupportedLangs.Spanish => CultureInfo.GetCultureInfo("es"),
SupportedLangs.SChinese => CultureInfo.GetCultureInfo("zh-Hans"),
SupportedLangs.TChinese => CultureInfo.GetCultureInfo("zh-Hant"),
SupportedLangs.Irish => CultureInfo.GetCultureInfo("ga"),
_ => throw new ArgumentOutOfRangeException(nameof(language), language, null),
};
}
}
+111
View File
@@ -0,0 +1,111 @@
using System.Collections.Generic;
using Il2CppInterop.Runtime.InteropTypes.Arrays;
namespace Reactor.Localization;
/// <summary>
/// Handles custom <see cref="StringNames"/> localization.
/// </summary>
public static class LocalizationManager
{
private static readonly List<LocalizationProvider> _providers = new();
/// <summary>
/// Gets registered <see cref="LocalizationProvider"/>s.
/// </summary>
public static IReadOnlyList<LocalizationProvider> Providers { get; } = _providers.AsReadOnly();
/// <summary>
/// Registers a new <see cref="LocalizationProvider"/> to be used for obtaining translations.
/// </summary>
/// <param name="provider">A <see cref="LocalizationProvider"/> instance.</param>
public static void Register(LocalizationProvider provider)
{
if (!_providers.Contains(provider))
{
_providers.Add(provider);
if (TranslationController.InstanceExists)
{
provider.SetLanguage(TranslationController.Instance.currentLanguage.languageID);
}
_providers.Sort((a, b) => b.Priority - a.Priority);
}
}
/// <summary>
/// Unregisters a <see cref="LocalizationProvider"/>.
/// </summary>
/// <param name="provider">The <see cref="LocalizationProvider"/> to unregister.</param>
public static void Unregister(LocalizationProvider provider)
{
_providers.Remove(provider);
}
internal static bool TryGetTextFormatted(StringNames stringName, Il2CppReferenceArray<Il2CppSystem.Object> parts, out string text)
{
foreach (var provider in _providers)
{
if (provider.TryGetTextFormatted(stringName, parts, out text!))
{
return true;
}
}
text = string.Empty;
return false;
}
internal static bool TryGetText(StringNames stringName, out string text)
{
foreach (var provider in _providers)
{
if (provider.TryGetText(stringName, out text!))
{
return true;
}
}
text = string.Empty;
return false;
}
internal static bool TryGetStringName(SystemTypes systemType, out StringNames stringName)
{
foreach (var provider in _providers)
{
if (provider.TryGetStringName(systemType, out var stringNameNullable))
{
stringName = stringNameNullable!.Value;
return true;
}
}
stringName = default;
return false;
}
internal static bool TryGetStringName(TaskTypes taskTypes, out StringNames stringName)
{
foreach (var provider in _providers)
{
if (provider.TryGetStringName(taskTypes, out var stringNameNullable))
{
stringName = stringNameNullable!.Value;
return true;
}
}
stringName = default;
return false;
}
internal static void OnLanguageChanged(SupportedLangs newLanguage)
{
foreach (var provider in _providers)
{
provider.SetLanguage(newLanguage);
}
}
}
@@ -0,0 +1,90 @@
using Il2CppInterop.Runtime.InteropTypes.Arrays;
using Reactor.Utilities;
namespace Reactor.Localization;
/// <summary>
/// The required implementation of a localization provider class.
/// </summary>
public abstract class LocalizationProvider
{
/// <summary>
/// Gets the current language Among Us is set to.
/// <br/>
/// If used from <see cref="OnLanguageChanged"/>, this property will return the old language, not the new one.
/// </summary>
public SupportedLangs? CurrentLanguage { get; private set; }
/// <summary>
/// Gets the priority of this <see cref="LocalizationProvider"/>.
/// The higher the priority is, the earlier it will be invoked in relation to other providers.
/// <br/>
/// You can use the <see cref="ReactorPriority"/> class for this value if you want to make this easier.
/// </summary>
public virtual int Priority => 0;
/// <summary>
/// Returns the localized text for the given <see cref="StringNames"/>.
/// </summary>
/// <param name="stringName">The <see cref="StringNames"/> to localize.</param>
/// <param name="result">The <see cref="string"/> representation of the given <see cref="StringNames"/>.</param>
/// <returns>Whether or not this <see cref="LocalizationProvider"/> can handle this <see cref="StringNames"/>.</returns>
public virtual bool TryGetText(StringNames stringName, out string? result)
{
result = null;
return false;
}
/// <summary>
/// Returns the localized text for the given <see cref="StringNames"/>.
/// </summary>
/// <param name="stringName">The <see cref="StringNames"/> to localize.</param>
/// <param name="parts">The arguments used for formatting.</param>
/// <param name="result">The <see cref="string"/> representation of the given <see cref="StringNames"/>.</param>
/// <returns>Whether or not this <see cref="LocalizationProvider"/> can handle this <see cref="StringNames"/>.</returns>
public virtual bool TryGetTextFormatted(StringNames stringName, Il2CppReferenceArray<Il2CppSystem.Object> parts, out string? result)
{
if (!TryGetText(stringName, out result)) return false;
result = Il2CppSystem.String.Format(result, parts);
return true;
}
/// <summary>
/// Returns the <see cref="StringNames"/> equivalent for the given <see cref="SystemTypes"/>.
/// </summary>
/// <param name="systemType">The <see cref="SystemTypes"/> value.</param>
/// <param name="result">The <see cref="string"/> representation of the given <see cref="StringNames"/>.</param>
/// <returns>Whether or not this <see cref="LocalizationProvider"/> can handle this <see cref="StringNames"/>.</returns>
public virtual bool TryGetStringName(SystemTypes systemType, out StringNames? result)
{
result = null;
return false;
}
/// <summary>
/// Returns the <see cref="StringNames"/> equivalent for the given <see cref="TaskTypes"/>.
/// </summary>
/// <param name="taskType">The <see cref="TaskTypes"/> value.</param>
/// <param name="result">The <see cref="string"/> representation of the given <see cref="StringNames"/>.</param>
/// <returns>Whether or not this <see cref="LocalizationProvider"/> can handle this <see cref="StringNames"/>.</returns>
public virtual bool TryGetStringName(TaskTypes taskType, out StringNames? result)
{
result = null;
return false;
}
/// <summary>
/// This method is called when the Among Us language is changed by the user.
/// </summary>
/// <param name="newLanguage">The new language that Among Us has been set to.</param>
public virtual void OnLanguageChanged(SupportedLangs newLanguage)
{
}
internal void SetLanguage(SupportedLangs newLanguage)
{
OnLanguageChanged(newLanguage);
CurrentLanguage = newLanguage;
}
}
@@ -0,0 +1,85 @@
using HarmonyLib;
using Il2CppInterop.Runtime.InteropTypes.Arrays;
namespace Reactor.Localization.Patches;
[HarmonyPatch]
internal static class GetStringPatch
{
[HarmonyPatch(typeof(TranslationController), nameof(TranslationController.GetString), typeof(StringNames), typeof(Il2CppReferenceArray<Il2CppSystem.Object>))]
[HarmonyPatch(typeof(TranslationController), nameof(TranslationController.GetStringWithDefault), typeof(StringNames), typeof(string), typeof(Il2CppReferenceArray<Il2CppSystem.Object>))]
[HarmonyPrefix]
public static bool StringNamesPatch(StringNames id, Il2CppReferenceArray<Il2CppSystem.Object> parts, out string __result)
{
if (LocalizationManager.TryGetTextFormatted(id, parts, out __result))
{
return false;
}
return true;
}
[HarmonyPatch(typeof(TranslationController), nameof(TranslationController.GetString), typeof(SystemTypes))]
[HarmonyPrefix]
public static bool SystemTypesStringPatch(TranslationController __instance, SystemTypes room, ref string __result)
{
if (LocalizationManager.TryGetStringName(room, out var stringName))
{
if (LocalizationManager.TryGetText(stringName, out var text))
{
__result = text;
return false;
}
__result = __instance.GetString(stringName);
return false;
}
return true;
}
[HarmonyPatch(typeof(TranslationController), nameof(TranslationController.GetSystemName))]
[HarmonyPrefix]
public static bool SystemTypesStringNamesPatch(SystemTypes room, ref StringNames __result)
{
if (LocalizationManager.TryGetStringName(room, out var stringName))
{
__result = stringName;
return false;
}
return true;
}
[HarmonyPatch(typeof(TranslationController), nameof(TranslationController.GetString), typeof(TaskTypes))]
[HarmonyPrefix]
public static bool TaskTypesStringPatch(TranslationController __instance, TaskTypes task, ref string __result)
{
if (LocalizationManager.TryGetStringName(task, out var stringName))
{
if (LocalizationManager.TryGetText(stringName, out var text))
{
__result = text;
return false;
}
__result = __instance.GetString(stringName);
return false;
}
return true;
}
[HarmonyPatch(typeof(TranslationController), nameof(TranslationController.GetTaskName))]
[HarmonyPrefix]
public static bool TaskTypesStringNamesPatch(TaskTypes task, ref StringNames __result)
{
if (LocalizationManager.TryGetStringName(task, out var stringName))
{
__result = stringName;
return false;
}
return true;
}
}
@@ -0,0 +1,22 @@
using HarmonyLib;
namespace Reactor.Localization.Patches;
[HarmonyPatch]
internal static class LanguageChangedPatch
{
[HarmonyPatch(typeof(TranslationController), nameof(TranslationController.Initialize))]
[HarmonyPostfix]
public static void Initialize(TranslationController __instance)
{
if (TranslationController.Instance.GetInstanceID() == __instance.GetInstanceID())
LocalizationManager.OnLanguageChanged(__instance.currentLanguage.languageID);
}
[HarmonyPatch(typeof(TranslationController), nameof(TranslationController.SetLanguage))]
[HarmonyPostfix]
public static void SetLanguage(TranslationController __instance)
{
LocalizationManager.OnLanguageChanged(__instance.currentLanguage.languageID);
}
}
@@ -0,0 +1,36 @@
using System.Collections.Generic;
using Reactor.Utilities;
namespace Reactor.Localization.Providers;
/// <summary>
/// Utility for adding hard-coded localization.
/// </summary>
public sealed class HardCodedLocalizationProvider : LocalizationProvider
{
private static readonly Dictionary<StringNames, string> _strings = new();
/// <summary>
/// Adds a custom, hard-coded translation for a <see cref="StringNames"/>.
/// </summary>
/// <param name="stringName">The <see cref="StringNames"/>.</param>
/// <param name="value">The text.</param>
public static void Register(StringNames stringName, string value)
{
if (_strings.ContainsKey(stringName))
{
Warning($"Registering StringName {stringName} that already exists");
}
_strings[stringName] = value;
}
/// <inheritdoc/>
public override int Priority => ReactorPriority.Low;
/// <inheritdoc/>
public override bool TryGetText(StringNames stringName, out string? result)
{
return _strings.TryGetValue(stringName, out result);
}
}
@@ -0,0 +1,33 @@
using Reactor.Localization.Providers;
namespace Reactor.Localization.Utilities;
/// <summary>
/// Provides a way to use custom static <see cref="StringNames"/>.
/// </summary>
public static class CustomStringName
{
private static int _lastId = int.MinValue + 1;
/// <summary>
/// Creates an returns a unique <see cref="StringNames"/> value.
/// </summary>
/// <returns>A unique <see cref="StringNames"/>.</returns>
public static StringNames Create()
{
var id = _lastId++;
return (StringNames) id;
}
/// <summary>
/// Creates, registeres and returns a unique <see cref="StringNames"/> value.
/// </summary>
/// <param name="text">The text.</param>
/// <returns>A unique <see cref="StringNames"/>.</returns>
public static StringNames CreateAndRegister(string text)
{
var stringName = Create();
HardCodedLocalizationProvider.Register(stringName, text);
return stringName;
}
}
-28
View File
@@ -1,28 +0,0 @@
using BepInEx.IL2CPP;
using BepInEx.Logging;
namespace Reactor
{
public static class Logger<T> where T : BasePlugin
{
public static ManualLogSource Instance => PluginSingleton<T>.Instance.Log;
/// <inheritdoc cref="ManualLogSource.LogFatal"/>
public static void Fatal(object data) => Instance.LogFatal(data);
/// <inheritdoc cref="ManualLogSource.LogError"/>
public static void Error(object data) => Instance.LogError(data);
/// <inheritdoc cref="ManualLogSource.LogWarning"/>
public static void Warning(object data) => Instance.LogWarning(data);
/// <inheritdoc cref="ManualLogSource.LogMessage"/>
public static void Message(object data) => Instance.LogMessage(data);
/// <inheritdoc cref="ManualLogSource.LogInfo"/>
public static void Info(object data) => Instance.LogInfo(data);
/// <inheritdoc cref="ManualLogSource.LogDebug"/>
public static void Debug(object data) => Instance.LogDebug(data);
}
}
@@ -0,0 +1,56 @@
using System;
using System.Collections.Generic;
using System.Reflection;
using BepInEx.Unity.IL2CPP;
using HarmonyLib;
using Reactor.Networking.Serialization;
namespace Reactor.Networking.Attributes;
/// <summary>
/// Automatically registers a <see cref="MessageConverter{T}"/>.
/// </summary>
[AttributeUsage(AttributeTargets.Class)]
public sealed class MessageConverterAttribute : Attribute
{
private static readonly HashSet<Assembly> _registeredAssemblies = new();
/// <summary>
/// Registers all <see cref="MessageConverter{T}"/>s annotated with <see cref="MessageConverterAttribute"/> in the specified <paramref name="assembly"/>.
/// </summary>
/// <remarks>This is called automatically on plugin assemblies so you probably don't need to call this.</remarks>
/// <param name="assembly">The assembly to search.</param>
public static void Register(Assembly assembly)
{
if (_registeredAssemblies.Contains(assembly)) return;
_registeredAssemblies.Add(assembly);
foreach (var type in assembly.GetTypes())
{
var attribute = type.GetCustomAttribute<MessageConverterAttribute>();
if (attribute != null)
{
if (!type.IsSubclassOf(typeof(UnsafeMessageConverter)))
{
throw new InvalidOperationException($"Type {type.FullDescription()} has {nameof(MessageConverterAttribute)} but doesn't extend {nameof(UnsafeMessageConverter)}.");
}
try
{
var messageConverter = (UnsafeMessageConverter) Activator.CreateInstance(type)!;
MessageSerializer.Register(messageConverter);
}
catch (Exception e)
{
Warning($"Failed to register {type.FullDescription()}: {e}");
}
}
}
}
internal static void Initialize()
{
IL2CPPChainloader.Instance.PluginLoad += (_, assembly, _) => Register(assembly);
}
}
@@ -0,0 +1,88 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using BepInEx.Unity.IL2CPP;
using HarmonyLib;
using Hazel;
using Reactor.Networking.Rpc;
using Reactor.Utilities;
namespace Reactor.Networking.Attributes;
/// <summary>
/// Automatically registers a method rpc.
/// </summary>
[AttributeUsage(AttributeTargets.Method)]
public sealed class MethodRpcAttribute : Attribute
{
private static readonly HashSet<Assembly> _registeredAssemblies = new();
/// <summary>
/// Gets the id of the rpc.
/// </summary>
public uint Id { get; }
/// <summary>
/// Gets or sets the send option of the rpc.
/// </summary>
public SendOption SendOption { get; set; } = SendOption.Reliable;
/// <summary>
/// Gets or sets the local handling of the rpc.
/// </summary>
public RpcLocalHandling LocalHandling { get; set; } = RpcLocalHandling.Before;
/// <summary>
/// Gets or sets a value indicating whether the rpc should be sent immediately.
/// </summary>
public bool SendImmediately { get; set; }
/// <summary>
/// Initializes a new instance of the <see cref="MethodRpcAttribute"/> class.
/// </summary>
/// <param name="id">The id of the rpc.</param>
public MethodRpcAttribute(uint id)
{
Id = id;
}
/// <summary>
/// Registers all method rpc's annotated with <see cref="MethodRpcAttribute"/> in the specified <paramref name="assembly"/>.
/// </summary>
/// <remarks>This is called automatically on plugin assemblies so you probably don't need to call this.</remarks>
/// <param name="assembly">The assembly to search.</param>
/// <param name="plugin">The plugin to register the rpc to.</param>
public static void Register(Assembly assembly, BasePlugin plugin)
{
if (_registeredAssemblies.Contains(assembly)) return;
_registeredAssemblies.Add(assembly);
var methods = assembly.GetTypes()
.SelectMany(t => t.GetMethods(BindingFlags.Static | BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.Public));
foreach (var method in methods)
{
var attribute = method.GetCustomAttribute<MethodRpcAttribute>();
if (attribute == null)
{
continue;
}
try
{
var customRpc = new MethodRpc(plugin, method, attribute.Id, attribute.SendOption, attribute.LocalHandling, attribute.SendImmediately);
PluginSingleton<ReactorPlugin>.Instance.CustomRpcManager.Register(customRpc);
}
catch (Exception e)
{
Warning($"Failed to register {method.FullDescription()}: {e}");
}
}
}
internal static void Initialize()
{
IL2CPPChainloader.Instance.PluginLoad += (_, assembly, plugin) => Register(assembly, plugin);
}
}
@@ -0,0 +1,43 @@
using System;
using System.Linq;
using System.Reflection;
namespace Reactor.Networking.Attributes;
/// <summary>
/// Describes the <see cref="ModFlags"/> of the annotated plugin class.
/// </summary>
[AttributeUsage(AttributeTargets.Class)]
public sealed class ReactorModFlagsAttribute : Attribute
{
/// <summary>
/// Gets flags of the mod.
/// </summary>
public ModFlags Flags { get; }
/// <summary>
/// Initializes a new instance of the <see cref="ReactorModFlagsAttribute"/> class.
/// </summary>
/// <param name="flags">Flags of the mod.</param>
public ReactorModFlagsAttribute(ModFlags flags)
{
Flags = flags;
}
internal static ModFlags GetModFlags(Type type)
{
var attribute = type.GetCustomAttribute<ReactorModFlagsAttribute>();
if (attribute != null)
{
return attribute.Flags;
}
var metadataAttribute = type.Assembly.GetCustomAttributes<AssemblyMetadataAttribute>().SingleOrDefault(x => x.Key == "Reactor.ModFlags");
if (metadataAttribute is { Value: not null })
{
return Enum.Parse<ModFlags>(metadataAttribute.Value);
}
return ModFlags.None;
}
}
@@ -0,0 +1,65 @@
using System;
using System.Collections.Generic;
using System.Reflection;
using BepInEx.Unity.IL2CPP;
using HarmonyLib;
using Reactor.Networking.Rpc;
using Reactor.Utilities;
namespace Reactor.Networking.Attributes;
/// <summary>
/// Automatically registers a rpc.
/// </summary>
[AttributeUsage(AttributeTargets.Class)]
public sealed class RegisterCustomRpcAttribute : Attribute
{
private static readonly HashSet<Assembly> _registeredAssemblies = new();
/// <summary>
/// Gets the id of the rpc.
/// </summary>
public uint Id { get; }
/// <summary>
/// Initializes a new instance of the <see cref="RegisterCustomRpcAttribute"/> class.
/// </summary>
/// <param name="id">The id of the rpc.</param>
public RegisterCustomRpcAttribute(uint id)
{
Id = id;
}
/// <summary>
/// Registers all rpc's annotated with <see cref="RegisterCustomRpcAttribute"/> in the specified <paramref name="assembly"/>.
/// </summary>
/// <remarks>This is called automatically on plugin assemblies so you probably don't need to call this.</remarks>
/// <param name="assembly">The assembly to search.</param>
/// <param name="plugin">The plugin to register the rpc to.</param>
public static void Register(Assembly assembly, BasePlugin plugin)
{
if (_registeredAssemblies.Contains(assembly)) return;
_registeredAssemblies.Add(assembly);
foreach (var type in assembly.GetTypes())
{
var attribute = type.GetCustomAttribute<RegisterCustomRpcAttribute>();
if (attribute != null)
{
if (!type.IsSubclassOf(typeof(UnsafeCustomRpc)))
{
throw new InvalidOperationException($"Type {type.FullDescription()} has {nameof(RegisterCustomRpcAttribute)} but doesn't extend {nameof(UnsafeCustomRpc)}.");
}
var customRpc = (UnsafeCustomRpc) Activator.CreateInstance(type, plugin, attribute.Id)!;
PluginSingleton<ReactorPlugin>.Instance.CustomRpcManager.Register(customRpc);
}
}
}
internal static void Initialize()
{
IL2CPPChainloader.Instance.PluginLoad += (_, assembly, plugin) => Register(assembly, plugin);
}
}
-82
View File
@@ -1,82 +0,0 @@
using System;
using BepInEx.IL2CPP;
using Hazel;
using InnerNet;
namespace Reactor.Networking
{
public abstract class CustomRpc<TPlugin, TInnerNetObject, TData> : UnsafeCustomRpc where TPlugin : BasePlugin where TInnerNetObject : InnerNetObject
{
protected CustomRpc(TPlugin plugin, uint id) : base(plugin, id)
{
}
public TPlugin Plugin => (TPlugin) UnsafePlugin;
public override Type InnerNetObjectType => typeof(TInnerNetObject);
public abstract void Write(MessageWriter writer, TData data);
public abstract TData Read(MessageReader reader);
public abstract void Handle(TInnerNetObject innerNetObject, TData data);
public override void UnsafeWrite(MessageWriter writer, object data)
{
Write(writer, (TData) data);
}
public override object UnsafeRead(MessageReader reader)
{
return Read(reader);
}
public override void UnsafeHandle(InnerNetObject innerNetObject, object data)
{
Handle((TInnerNetObject) innerNetObject, (TData) data);
}
public void Send(InnerNetObject netObject, TData data, bool immediately = false)
{
UnsafeSend(netObject, data, immediately);
}
public void SendTo(InnerNetObject netObject, int targetId, TData data)
{
UnsafeSend(netObject, data, true, targetId);
}
}
public abstract class CustomRpc<TPlugin, TInnerNetObject> : UnsafeCustomRpc where TPlugin : BasePlugin where TInnerNetObject : InnerNetObject
{
protected CustomRpc(TPlugin plugin, uint id) : base(plugin, id)
{
}
public TPlugin Plugin => (TPlugin) UnsafePlugin;
public override Type InnerNetObjectType => typeof(TInnerNetObject);
public abstract void Handle(TInnerNetObject innerNetObject);
public override void UnsafeWrite(MessageWriter writer, object data)
{
}
public override object UnsafeRead(MessageReader reader)
{
return null;
}
public override void UnsafeHandle(InnerNetObject innerNetObject, object data)
{
Handle((TInnerNetObject) innerNetObject);
}
public void Send(InnerNetObject netObject, bool immediately = false)
{
UnsafeSend(netObject, immediately);
}
public void SendTo(InnerNetObject netObject, int targetId)
{
UnsafeSend(netObject, null, true, targetId);
}
}
}
-115
View File
@@ -1,115 +0,0 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using HarmonyLib;
using Hazel;
using InnerNet;
namespace Reactor.Networking
{
public enum RpcLocalHandling
{
None,
Before,
After
}
public class CustomRpcManager
{
public const byte CallId = byte.MaxValue;
private readonly List<UnsafeCustomRpc> _list = new List<UnsafeCustomRpc>();
private readonly Dictionary<Type, List<UnsafeCustomRpc>> _map = new Dictionary<Type, List<UnsafeCustomRpc>>();
public IReadOnlyList<UnsafeCustomRpc> List => _list.AsReadOnly();
public ILookup<Type, UnsafeCustomRpc> Map =>
_map.SelectMany(pair => pair.Value, (pair, value) => new { pair.Key, Value = value })
.ToLookup(pair => pair.Key, pair => pair.Value);
public CustomRpcManager()
{
foreach (var type in HandleRpcPatch.InnerNetObjectTypes)
{
_map[type] = new List<UnsafeCustomRpc>();
}
}
public UnsafeCustomRpc Register(UnsafeCustomRpc customRpc)
{
if (_list.Any(x => x.UnsafePlugin == customRpc.UnsafePlugin && x.Id == customRpc.Id))
{
throw new ArgumentException("Rpc with that id was already registered");
}
customRpc.Manager = this;
_list.Add(customRpc);
_map[customRpc.InnerNetObjectType].Add(customRpc);
typeof(Rpc<>).MakeGenericType(customRpc.GetType()).GetProperty("Instance")!.SetValue(null, customRpc);
return customRpc;
}
[HarmonyPatch]
private static class HandleRpcPatch
{
internal static List<Type> InnerNetObjectTypes { get; } = typeof(InnerNetObject).Assembly.GetTypes().Where(x => x.IsSubclassOf(typeof(InnerNetObject)) && x != typeof(LobbyBehaviour)).ToList();
public static IEnumerable<MethodBase> TargetMethods()
{
return InnerNetObjectTypes.Select(x => x.GetMethod(nameof(InnerNetObject.HandleRpc), AccessTools.all));
}
public static bool Prefix(InnerNetObject __instance, [HarmonyArgument(0)] byte callId, [HarmonyArgument(1)] MessageReader reader)
{
if (callId == CallId)
{
var manager = PluginSingleton<ReactorPlugin>.Instance.CustomRpcManager;
var customRpcs = manager.Map[__instance.GetType()];
var pluginNetId = reader.ReadPackedUInt32();
var id = reader.ReadPackedUInt32();
var pluginId = ModList.GetByNetId(pluginNetId).Id;
var customRpc = customRpcs.Single(x => x.PluginId == pluginId && x.Id == id);
customRpc.UnsafeHandle(__instance, customRpc.UnsafeRead(reader.ReadMessage()));
return false;
}
return true;
}
}
}
public static class Rpc<T> where T : UnsafeCustomRpc
{
private static T _instance;
public static T Instance
{
get
{
if (_instance == null)
{
throw new Exception($"{typeof(T).FullName} isn't registered");
}
return _instance;
}
internal set
{
if (_instance != null)
{
throw new Exception($"{typeof(T).FullName} is already registered");
}
_instance = value;
}
}
}
}
@@ -0,0 +1,46 @@
using Hazel;
using InnerNet;
namespace Reactor.Networking.Extensions;
/// <summary>
/// Provides extension methods for <see cref="InnerNetClient"/>.
/// </summary>
public static class ClientExtensions
{
/// <summary>
/// Kicks a client with id equal to <paramref name="targetClientId"/> with a <paramref name="reason"/>.
/// </summary>
/// <param name="innerNetClient">The <see cref="InnerNetClient"/> to send the message from.</param>
/// <param name="targetClientId">The target client's id.</param>
/// <param name="reason">The kick reason.</param>
internal static void KickWithReason(this InnerNetClient innerNetClient, int targetClientId, string reason)
{
var writer = MessageWriter.Get(SendOption.Reliable);
writer.StartMessage(Tags.GameDataTo);
writer.Write(innerNetClient.GameId);
writer.WritePacked(targetClientId);
{
writer.StartMessage(byte.MaxValue);
writer.Write((byte) ReactorGameDataFlag.SetKickReason);
writer.Write(reason);
writer.EndMessage();
}
writer.EndMessage();
innerNetClient.SendOrDisconnect(writer);
writer.Recycle();
innerNetClient.KickPlayer(targetClientId, false);
}
/// <summary>
/// Disconnects a local <see cref="InnerNetClient"/> with a custom reason.
/// </summary>
/// <param name="innerNetClient">The <see cref="InnerNetClient"/> to disconnect.</param>
/// <param name="reason">The custom reason to disconnect with.</param>
public static void DisconnectWithReason(this InnerNetClient innerNetClient, string reason)
{
innerNetClient.LastCustomDisconnect = reason;
innerNetClient.HandleDisconnect(innerNetClient.LastDisconnectReason = DisconnectReasons.Custom, reason);
}
}
@@ -0,0 +1,67 @@
using System;
using Hazel;
using Hazel.Udp;
using UnityEngine;
namespace Reactor.Networking.Extensions;
/// <summary>
/// Provides extension methods for <see cref="MessageWriter"/> and <see cref="MessageReader"/>.
/// </summary>
public static class ExtraMessageExtensions
{
private const float MIN = -50f;
private const float MAX = 50f;
private static float ReverseLerp(float t)
{
return Mathf.Clamp((t - MIN) / (MAX - MIN), 0f, 1f);
}
/// <summary>
/// Writes a <see cref="Vector2"/> to the <paramref name="writer"/>.
/// </summary>
/// <param name="writer">The <see cref="MessageWriter"/> to write to.</param>
/// <param name="value">The <see cref="Vector2"/> to write.</param>
public static void Write(this MessageWriter writer, Vector2 value)
{
var x = (ushort) (ReverseLerp(value.x) * ushort.MaxValue);
var y = (ushort) (ReverseLerp(value.y) * ushort.MaxValue);
writer.Write(x);
writer.Write(y);
}
/// <summary>
/// Reads a <see cref="Vector2"/> from the <paramref name="reader"/>.
/// </summary>
/// <param name="reader">The <see cref="MessageReader"/> to read from.</param>
/// <returns>A <see cref="Vector2"/> from the <paramref name="reader"/>.</returns>
public static Vector2 ReadVector2(this MessageReader reader)
{
var x = reader.ReadUInt16() / (float) ushort.MaxValue;
var y = reader.ReadUInt16() / (float) ushort.MaxValue;
return new Vector2(Mathf.Lerp(MIN, MAX, x), Mathf.Lerp(MIN, MAX, y));
}
/// <summary>
/// Sends a message on the <paramref name="connection"/> with an <paramref name="ackCallback"/>.
/// </summary>
/// <param name="connection">The connection to send the message on.</param>
/// <param name="msg">The message to send.</param>
/// <param name="ackCallback">The callback to invoke when this packet is acknowledged.</param>
public static void Send(this UdpConnection connection, MessageWriter msg, Action ackCallback)
{
if (msg.SendOption != SendOption.Reliable)
throw new InvalidOperationException("Message SendOption has to be Reliable.");
var buffer = new byte[msg.Length];
Buffer.BlockCopy(msg.Buffer, 0, buffer, 0, msg.Length);
connection.ResetKeepAliveTimer();
connection.AttachReliableID(buffer, 1, ackCallback);
connection.WriteBytesToConnection(buffer, buffer.Length);
}
}
@@ -0,0 +1,35 @@
using System.Collections.Generic;
using Hazel;
namespace Reactor.Networking.Messages;
internal static class ModdedHandshakeC2S
{
public static void Serialize(MessageWriter writer, IReadOnlyCollection<Mod> mods)
{
writer.WritePacked(mods.Count);
foreach (var mod in mods)
{
writer.Write(mod.Id);
writer.Write(mod.Version);
writer.Write((ushort) mod.Flags);
if (mod.IsRequiredOnAllClients) writer.Write(mod.Name);
}
}
public static void Deserialize(MessageReader reader, out Mod[] mods)
{
var modCount = reader.ReadPackedInt32();
mods = new Mod[modCount];
for (var i = 0; i < modCount; i++)
{
var id = reader.ReadString();
var version = reader.ReadString();
var flags = (ModFlags) reader.ReadUInt16();
var name = (flags & ModFlags.RequireOnAllClients) != 0 ? reader.ReadString() : null;
mods[i] = new Mod(id, version, flags, name);
}
}
}
@@ -0,0 +1,20 @@
using Hazel;
namespace Reactor.Networking.Messages;
internal static class ModdedHandshakeS2C
{
public static void Serialize(MessageWriter writer, string serverName, string serverVersion, int pluginCount)
{
writer.Write(serverName);
writer.Write(serverVersion);
writer.WritePacked(pluginCount);
}
public static void Deserialize(MessageReader reader, out string serverName, out string serverVersion, out int pluginCount)
{
serverName = reader.ReadString();
serverVersion = reader.ReadString();
pluginCount = reader.ReadPackedInt32();
}
}
@@ -0,0 +1,30 @@
using Hazel;
namespace Reactor.Networking.Messages;
internal static class ReactorHeader
{
private const ulong MAGIC = 0x72656163746f72; // "reactor" in ascii, 7 bytes
public static int Size => sizeof(ulong);
public static void Read(MessageReader reader, out ulong magic, out byte version)
{
var value = reader.ReadUInt64();
magic = value >> 8;
version = (byte) (value & 0xFF);
}
public static bool Read(MessageReader reader)
{
Read(reader, out var magic, out var version);
return magic == MAGIC && version == (int) ReactorProtocolVersion.Latest;
}
public static void Write(MessageWriter writer)
{
var version = (byte) ReactorProtocolVersion.Latest;
var value = (MAGIC << 8) | version;
writer.Write(value);
}
}
-17
View File
@@ -1,17 +0,0 @@
using Hazel;
namespace Reactor.Networking
{
public static class ModDeclaration
{
public static void Serialize(MessageWriter writer, Mod mod)
{
writer.StartMessage(byte.MaxValue);
writer.Write((byte) ReactorMessageFlags.ModDeclaration);
writer.WritePacked(mod.NetId);
writer.Write(mod.Id);
writer.Write(mod.Version);
writer.Write((byte) mod.Side);
}
}
}
+142 -27
View File
@@ -1,43 +1,158 @@
using System;
using System.Collections.Generic;
using System.Globalization;
using System.Linq;
using System.Reflection;
using BepInEx.IL2CPP;
using System.Text;
using BepInEx;
using BepInEx.Unity.IL2CPP;
using Hazel;
using Reactor.Networking.Attributes;
using Reactor.Networking.Patches;
namespace Reactor.Networking
namespace Reactor.Networking;
/// <summary>
/// Represents currently loaded mods.
/// </summary>
public static class ModList
{
public static class ModList
/// <summary>
/// Gets current mods.
/// </summary>
public static IReadOnlyCollection<Mod> Current { get; private set; } = null!;
private static readonly Dictionary<string, Mod> _modById = new();
private static readonly Dictionary<Type, Mod> _modByPluginType = new();
/// <summary>
/// Gets a mod by it's id.
/// </summary>
/// <param name="id">The id of the mod.</param>
/// <returns>The mod with the specified <paramref name="id"/>.</returns>
public static Mod GetById(string id)
{
private static Dictionary<string, Mod> _mapById;
private static Dictionary<uint, Mod> _mapByNetId;
return _modById[id];
}
public static ISet<Mod> Current { get; private set; }
internal static Mod GetByPluginType(Type pluginType)
{
return _modByPluginType[pluginType];
}
public static Mod GetById(string id)
internal static bool IsAnyModIsRequiredOnAllClients { get; private set; }
private static readonly Dictionary<uint, Mod> _modByNetId = new();
private static readonly Dictionary<Mod, uint> _netIdByMod = new();
internal static Mod GetByNetId(uint netId)
{
return _modByNetId[netId];
}
internal static uint GetNetId(this Mod mod)
{
if (!mod.IsRequiredOnAllClients) throw new ArgumentException("Cannot get a net id for a mod without RequireOnAllClients flag", nameof(mod));
return _netIdByMod[mod];
}
/// <summary>
/// Reads a <see cref="Mod"/> reference from the <paramref name="reader"/>.
/// </summary>
/// <param name="reader">The <see cref="MessageReader"/> to read from.</param>
/// <returns>A <see cref="Mod"/> from the <paramref name="reader"/>.</returns>
/// <remarks>This will try to read by net id and fallback to a regular id otherwise.</remarks>
public static Mod ReadMod(this MessageReader reader)
{
var netId = reader.ReadPackedUInt32();
if (netId > 0)
{
return _mapById[id];
return GetByNetId(netId);
}
public static Mod GetByNetId(uint netId)
var id = reader.ReadString();
return GetById(id);
}
/// <summary>
/// Writes a <see cref="Mod"/> reference to the <paramref name="writer"/>.
/// </summary>
/// <param name="writer">The <see cref="MessageWriter"/> to write to.</param>
/// <param name="value">The <see cref="Mod"/> to write.</param>
/// <remarks>This will write the net id if <see cref="Mod.IsRequiredOnAllClients"/> is true, regular id otherwise.</remarks>
public static void Write(this MessageWriter writer, Mod value)
{
if (value.IsRequiredOnAllClients)
{
return _mapByNetId[netId];
writer.WritePacked(value.GetNetId());
}
internal static void Update()
else
{
var i = (uint) 0;
Current = IL2CPPChainloader.Instance.Plugins.Values
.OrderByDescending(x => x.Metadata.GUID == ReactorPlugin.Id)
.Select(plugin => new Mod(
i++,
plugin.Metadata.GUID,
plugin.Metadata.Version.Clean(),
plugin.Instance.GetType().GetCustomAttribute<ReactorPluginSideAttribute>()?.Side ?? PluginSide.Both
))
.ToHashSet();
_mapById = Current.ToDictionary(mod => mod.Id, mod => mod);
_mapByNetId = Current.ToDictionary(mod => mod.NetId, mod => mod);
writer.WritePacked(0);
writer.Write(value.Id);
}
}
private static void Refresh()
{
if (ReactorConnection.Instance != null) throw new InvalidOperationException("Can't refresh the mod list during a connection");
Current = IL2CPPChainloader.Instance.Plugins.Values
.Select(pluginInfo => GetById(pluginInfo.Metadata.GUID))
.OrderByDescending(x => x.Id == ReactorPlugin.Id)
.ThenBy(x => x.Id, StringComparer.Ordinal)
.ToHashSet();
_modByNetId.Clear();
_netIdByMod.Clear();
uint netId = 1;
foreach (var mod in Current)
{
if (!mod.IsRequiredOnAllClients) continue;
_modByNetId[netId] = mod;
_netIdByMod[mod] = netId;
netId++;
}
IsAnyModIsRequiredOnAllClients = Current.Any(m => m.IsRequiredOnAllClients);
var debug = new StringBuilder("Mod list:");
foreach (var mod in Current)
{
debug.AppendLine();
debug.Append(CultureInfo.InvariantCulture, $" - {mod.Id} version: {mod.Version}, flags: {mod.Flags}");
if (mod.IsRequiredOnAllClients) debug.Append(CultureInfo.InvariantCulture, $", netId: {mod.GetNetId()}");
}
Debug(debug.ToString());
}
private static void OnPluginLoad(PluginInfo pluginInfo, BasePlugin plugin)
{
var pluginType = plugin.GetType();
var mod = new Mod(
pluginInfo.Metadata.GUID,
pluginInfo.Metadata.Version.Clean(),
ReactorModFlagsAttribute.GetModFlags(pluginType),
pluginInfo.Metadata.Name
);
_modById[mod.Id] = mod;
_modByPluginType[pluginType] = mod;
}
internal static void Initialize()
{
foreach (var existingPlugin in IL2CPPChainloader.Instance.Plugins.Values)
{
if (existingPlugin.Instance == null) continue;
OnPluginLoad(existingPlugin, (BasePlugin) existingPlugin.Instance);
}
IL2CPPChainloader.Instance.PluginLoad += (pluginInfo, _, plugin) => OnPluginLoad(pluginInfo, plugin);
IL2CPPChainloader.Instance.Finished += Refresh;
}
}
-13
View File
@@ -1,13 +0,0 @@
using Hazel;
namespace Reactor.Networking
{
public static class ModdedHandshakeC2S
{
public static void Serialize(MessageWriter writer, int modCount)
{
writer.Write((byte) ReactorProtocolVersion.Initial);
writer.WritePacked(modCount);
}
}
}
-24
View File
@@ -1,24 +0,0 @@
using Hazel;
namespace Reactor.Networking
{
public static class ModdedHandshakeS2C
{
public static void Serialize(MessageWriter writer, string serverName, string serverVersion, int pluginCount)
{
writer.StartMessage(byte.MaxValue);
writer.Write((byte) ReactorMessageFlags.Handshake);
writer.Write(serverName);
writer.Write(serverVersion);
writer.WritePacked(pluginCount);
writer.EndMessage();
}
public static void Deserialize(MessageReader reader, out string serverName, out string serverVersion, out int pluginCount)
{
serverName = reader.ReadString();
serverVersion = reader.ReadString();
pluginCount = reader.ReadPackedInt32();
}
}
}
Loaded 100 of 170 files, more files were not shown because too many files have changed in this diff. Show more