diff --git a/.editorconfig b/.editorconfig index c96fce69ad..1adb987c63 100644 --- a/.editorconfig +++ b/.editorconfig @@ -7,11 +7,48 @@ indent_style = space end_of_line = lf # ReSharper properties +resharper_blank_lines_after_block_statements = 0 +resharper_braces_for_ifelse = required_for_multiline +resharper_braces_redundant = false +resharper_keep_existing_attribute_arrangement = true resharper_wrap_object_and_collection_initializer_style = chop_if_long -[*.{proj, csproj, targets}] +[*.{proj,csproj,props,targets}] indent_size = 4 insert_final_newline = true +tab_width = 4 +dotnet_style_operator_placement_when_wrapping = beginning_of_line +dotnet_style_readonly_field = true:suggestion +dotnet_style_require_accessibility_modifiers = for_non_interface_members:silent +dotnet_style_coalesce_expression = true:suggestion +dotnet_style_null_propagation = true:suggestion +dotnet_style_prefer_is_null_check_over_reference_equality_method = true:suggestion +dotnet_style_prefer_auto_properties = true:silent +dotnet_style_object_initializer = true:suggestion +dotnet_style_prefer_collection_expression = true:suggestion +dotnet_style_namespace_match_folder = true:suggestion +dotnet_style_collection_initializer = true:suggestion +dotnet_style_prefer_simplified_boolean_expressions = true:suggestion +dotnet_style_prefer_conditional_expression_over_assignment = true:silent +dotnet_style_prefer_conditional_expression_over_return = true:silent +dotnet_style_explicit_tuple_names = true:suggestion +dotnet_style_prefer_inferred_tuple_names = true:suggestion +dotnet_style_prefer_inferred_anonymous_type_member_names = true:suggestion +dotnet_style_prefer_compound_assignment = true:suggestion +dotnet_style_prefer_simplified_interpolation = true:suggestion +dotnet_style_allow_multiple_blank_lines_experimental = true:silent +dotnet_style_allow_statement_immediately_after_block_experimental = true:silent +dotnet_code_quality_unused_parameters = all:suggestion +dotnet_style_parentheses_in_arithmetic_binary_operators = always_for_clarity:silent +dotnet_style_parentheses_in_other_binary_operators = always_for_clarity:silent +dotnet_style_parentheses_in_relational_binary_operators = always_for_clarity:silent +dotnet_style_parentheses_in_other_operators = never_if_unnecessary:silent +dotnet_style_qualification_for_field = false:silent +dotnet_style_qualification_for_property = false:silent +dotnet_style_qualification_for_method = false:silent +dotnet_style_qualification_for_event = false:silent +dotnet_style_predefined_type_for_locals_parameters_members = true:silent +dotnet_style_predefined_type_for_member_access = true:silent [App.config] indent_size = 4 @@ -21,6 +58,54 @@ insert_final_newline = true indent_size = 4 insert_final_newline = true charset = utf-8 +csharp_space_around_binary_operators = before_and_after +csharp_indent_labels = one_less_than_current +csharp_style_expression_bodied_methods = false:silent +csharp_style_expression_bodied_constructors = false:silent +csharp_style_expression_bodied_operators = false:silent +csharp_style_expression_bodied_properties = true:silent +csharp_style_expression_bodied_indexers = true:silent +csharp_style_expression_bodied_accessors = true:silent +csharp_style_expression_bodied_lambdas = true:silent +csharp_style_expression_bodied_local_functions = false:silent +csharp_style_prefer_switch_expression = true:suggestion +csharp_style_prefer_pattern_matching = true:silent +csharp_style_pattern_matching_over_is_with_cast_check = true:suggestion +csharp_style_pattern_matching_over_as_with_null_check = true:suggestion +csharp_style_prefer_not_pattern = true:suggestion +csharp_style_prefer_extended_property_pattern = true:suggestion +csharp_prefer_simple_using_statement = true:suggestion +csharp_prefer_braces = true:silent +csharp_style_namespace_declarations = file_scoped:suggestion +csharp_style_prefer_method_group_conversion = true:silent +csharp_style_prefer_top_level_statements = true:silent +csharp_style_prefer_primary_constructors = true:suggestion +csharp_prefer_static_local_function = true:suggestion +csharp_style_prefer_readonly_struct = true:suggestion +csharp_style_prefer_readonly_struct_member = true:suggestion +csharp_style_throw_expression = true:suggestion +csharp_style_prefer_null_check_over_type_check = true:suggestion +csharp_prefer_simple_default_expression = true:suggestion +csharp_style_prefer_local_over_anonymous_function = true:suggestion +csharp_style_prefer_index_operator = true:suggestion +csharp_style_prefer_range_operator = true:suggestion +csharp_style_implicit_object_creation_when_type_is_apparent = true:suggestion +csharp_style_prefer_tuple_swap = true:suggestion +csharp_style_prefer_utf8_string_literals = true:suggestion +csharp_style_inlined_variable_declaration = true:suggestion +csharp_style_deconstructed_variable_declaration = true:suggestion +csharp_style_unused_value_assignment_preference = discard_variable:suggestion +csharp_style_unused_value_expression_statement_preference = discard_variable:silent +csharp_style_allow_embedded_statements_on_same_line_experimental = true:silent +csharp_style_allow_blank_lines_between_consecutive_braces_experimental = true:silent +csharp_style_allow_blank_line_after_colon_in_constructor_initializer_experimental = true:silent +csharp_style_allow_blank_line_after_token_in_conditional_expression_experimental = true:silent +csharp_style_allow_blank_line_after_token_in_arrow_expression_clause_experimental = true:silent +csharp_style_var_for_built_in_types = false:silent +csharp_style_var_when_type_is_apparent = false:silent +csharp_style_var_elsewhere = false:silent +csharp_style_conditional_delegate_call = true:suggestion +csharp_using_directive_placement = outside_namespace:silent [*.g.cs] generated_code = true diff --git a/.github/ISSUE_TEMPLATE/bug_report.yaml b/.github/ISSUE_TEMPLATE/bug_report.yaml index bf0bdda66f..d74beb73c4 100644 --- a/.github/ISSUE_TEMPLATE/bug_report.yaml +++ b/.github/ISSUE_TEMPLATE/bug_report.yaml @@ -24,7 +24,7 @@ body: id: os_type attributes: label: Which OS are you playing on? - description: Please select your Operation System from the dropdown. + description: Please select your Operating System from the dropdown. options: - Windows - Linux (currently not supported, don't file any reports if your are using this) @@ -55,7 +55,7 @@ body: id: steps_to_reproduce attributes: label: Describe the steps you took to encounter the bug. - description: How did it happened? Please provide steps to reproduce the bug if possible. Did the bug disappear with slightly altered steps? + description: How did it happen? Please provide steps to reproduce the bug if possible. Did the bug disappear with slightly altered steps? placeholder: Tell us what you did! validations: required: false @@ -65,7 +65,7 @@ body: label: Relevant log output description: | Please upload your game logs if possible. The logs are located next to the launcher in a folder called "Nitrox Logs". - Upload the most recent "game-XXXXXXXX.log" and if you hosted the server also "server-XXXXXXXX.log" to [Pastbin](https://pastebin.com/). + Upload the most recent "game-XXXXXXXX.log" and if you hosted the server also "server-XXXXXXXX.log" to [Pastebin](https://pastebin.com/). After you created a paste for both files post their links into this box. placeholder: | For example: diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 0dd96d0ad6..fcca109968 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -1,56 +1,3 @@ # Contributing -## Code -We do not have a formatting guideline *yet*, and expect you to write code with common sense in mind. Consistency is key, so look at the surrounding code and adhere to the same standards. Always check the diff before you commit (and more importantly: before filing a PR); many irrelevant changes usually mean your autoformat settings are off. Luckily, our project now includes a `.editorconfig` that automatically sets all the built-in formatting/language-rules. This is however only supported in Visual Studio 2017. -A large list of discussion items has been compiled [here](https://github.com/SubnauticaNitrox/Nitrox/issues/36), which hopefully make it into a guideline soon™. - -### Formatting -- Use UpperCamelCase for methods, classes, properties and public fields. -- Use lowerCamelCase for local variables, private fields and function parameters. -- Remove unused `using` statements (Visual Studio has a shortcut to do this, as well as sort them). -- Put opening braces (`{`) on their own line. -- Encapsulate everything in braces, even single-line statements. -- Use `Optional` for explicit nullable types. -- Use strict access modifiers where possible, and mark immutable variables wherever appropriate (`const`, `readonly` or `static readonly`, depending on the usecase). -- Remove `private set;` from properties if these are only assigned in the constructor. -- Assign simple data types (that do not require arguments) at declaration rather than in the constructor (such as `private readonly List someList = new List();`, instead of putting the `new` part in the constructor). - -Again, consistency is key! If you're unsure, look at the rest of the code! - -### Safe guidelines -When retrieving data from the game, use `Validate.NotNull` or similar where possible. Subnautica is still heavily under development, and things *will* change. Defensive coding standards help identify and fix these changes more easily. -To reduce redundant if sturctures, there are several helper functions that combine a certain retrieval function with a `Validation` check - it's recommended to use these. For example `GameObject.RequireComponent` and `GuidHelper.RequireObjectFrom`. In case of `Optional` return types, these are unwrapped for you as well, saving the redundant checks *and* unwrapping. - -### Help your fellow developers! -If code (especially patches that touch game internals) is/are not immediately clear, add a comment explaining the situation. This goes a long way, as you're basically presenting an overview of the research you did in the game code. And it helps others to figure out what's supposed to happen, in case the game changes and the patch is not functioning properly anymore. - -### General OO(P) concepts -... such as "low coupling" and "high coherency", which basically means that you should try to reduce interaction between different pieces of code (classes) as much as possible (low coupling), and make sure that these pieces of code (classes) do the thing they are meant to do, and nothing else (high coherency). This goes a long way in code maintainability; less spaghetti code is always better :wink: -Also in this case, keep common sense in mind: if you're constantly accessing a lot of fields and methods of another class, consider tucking it away in a method in that class. - -## Git workflow -### Git help -Skip this section is if you are familiar with git. -Git is there to help you develop and share code efficiently, though it may seem daunting at first. In order to use it effectively, we recommend you to read some tutorials so that you are familiar with the concept of commits, the way these are linked together, branches, and remotes. - -When cloning a repository, git adds the clone url as a remote named `origin`. In this guide, we assume that's your fork. To keep your repository updated, add this official repo to your remotes: -```bash -# SSH: -git remote add upstream git@github.com:SubnauticaNitrox/Nitrox.git -# HTTPS: -git remote add upstream https://github.com/SubnauticaNitrox/Nitrox.git -``` - -We recommend to keep your master branch up to date with the offical master branch. This makes it easier to base feature branches on. -To go even further, you configure your master branch to pull from `SubnauticaNitrox`, and push to your own fork: -```bash -git config branch.master.remote upstream -git config branch.master.pushRemote origin -``` - -### Filing a PR -When filing a PR, we obviously expect the code to compile, run with no errors, and merge without conflicts. -To prevent these, and ensure that your code is compatible with the most recent 'version', -merge master into your branch, or rebase your branch on top of master. Even if git(hub) says your code can be merged without conflicts, there might be structural changes (renamings, moved files, refactors, etc), causing the final result to fail compilation, or break at runtime. - -It is not desired to remove code just because "it doesn't work", or "causes exceptions in the log". If that's the case, try to fix it (recommended to file the changes in a separate PR), or notify the other Nitrox devs (by creating an issue on github, for example). All code is there for a reason - and someone else spent time creating it. +Please have a look at our [documentation site](https://subnauticanitrox.github.io/Documentation/) for contribution guidelines & information on how to get started. \ No newline at end of file diff --git a/Directory.Build.props b/Directory.Build.props index d7d20f8422..78c3b23ca0 100644 --- a/Directory.Build.props +++ b/Directory.Build.props @@ -1,7 +1,7 @@ - 11 + 12.0 1.8.0.0 false false @@ -12,16 +12,18 @@ $(BuildGenDir)publicized_assemblies\ true false + embedded false disable $(MSBuildProjectDirectory)=$(MSBuildProjectName) true + true true - + true @@ -30,27 +32,27 @@ true + + DEBUG;BELOWZERO + bin\BelowZero\ + + - + JB - - all - runtime; build; native; contentfiles; analyzers; buildtransitive - - - - - - - - - + + all + runtime; build; native; contentfiles; analyzers + + + + @@ -67,6 +69,10 @@ NitroxModel + + all + runtime; build; native; contentfiles; analyzers; buildtransitive + diff --git a/Directory.Build.targets b/Directory.Build.targets index 8b5dbb79ec..3ade8e7cb2 100644 --- a/Directory.Build.targets +++ b/Directory.Build.targets @@ -4,6 +4,10 @@ + + $(GameManagedDir)\FMODUnity.dll + $(TestLibrary) + $(GameManagedDir)\Newtonsoft.Json.dll $(TestLibrary) diff --git a/Nitrox.Analyzers/Diagnostics/EnumeratorUsageAnalyzer.cs b/Nitrox.Analyzers/Diagnostics/EnumeratorUsageAnalyzer.cs deleted file mode 100644 index 22e93cac8f..0000000000 --- a/Nitrox.Analyzers/Diagnostics/EnumeratorUsageAnalyzer.cs +++ /dev/null @@ -1,61 +0,0 @@ -using System.Collections; -using System.Collections.Immutable; -using Microsoft.CodeAnalysis; -using Microsoft.CodeAnalysis.CSharp; -using Microsoft.CodeAnalysis.CSharp.Syntax; -using Microsoft.CodeAnalysis.Diagnostics; -using Nitrox.Analyzers.Extensions; - -namespace Nitrox.Analyzers.Diagnostics; - -/// -/// Test that calls to a method returning an IEnumerator are iterated (MoveNext is called). If they aren't iterated than the code in them won't -/// continue after the first 'yield return'. -/// -[DiagnosticAnalyzer(LanguageNames.CSharp)] -public sealed class EnumeratorUsageAnalyzer : DiagnosticAnalyzer -{ - public const string UNUSED_ENUMERATOR = $"{nameof(EnumeratorUsageAnalyzer)}001"; - - private static readonly DiagnosticDescriptor unusedEnumerator = new(UNUSED_ENUMERATOR, - "IEnumerator is not iterated", - $"The IEnumerator '{{0}}' must be iterated by calling its {nameof(IEnumerator.MoveNext)} otherwise it will stop executing at the first 'yield return' expression", - "Usage", - DiagnosticSeverity.Warning, - true); - - public override ImmutableArray SupportedDiagnostics => ImmutableArray.Create(unusedEnumerator); - - public override void Initialize(AnalysisContext context) - { - context.ConfigureGeneratedCodeAnalysis(GeneratedCodeAnalysisFlags.None); - context.EnableConcurrentExecution(); - - context.RegisterSyntaxNodeAction(static c => AnalyzeIEnumeratorInvocation(c), SyntaxKind.InvocationExpression); - } - - private static void AnalyzeIEnumeratorInvocation(SyntaxNodeAnalysisContext context) - { - InvocationExpressionSyntax expression = (InvocationExpressionSyntax)context.Node; - if (expression.Parent == null) - { - return; - } - IMethodSymbol methodSymbol = context.SemanticModel.GetSymbolInfo(expression, context.CancellationToken).Symbol as IMethodSymbol; - if (methodSymbol == null) - { - return; - } - // Ignore if method invoke is used/wrapped by something (variable declaration, as a parameter, etc). - if (!expression.Parent.IsKind(SyntaxKind.ExpressionStatement)) - { - return; - } - if (!methodSymbol.ReturnType.IsType(context.SemanticModel, "System.Collections.IEnumerator")) - { - return; - } - - context.ReportDiagnostic(Diagnostic.Create(unusedEnumerator, expression.GetLocation(), methodSymbol.Name)); - } -} diff --git a/Nitrox.Analyzers/Diagnostics/LocalizationAnalyzer.cs b/Nitrox.Analyzers/Diagnostics/LocalizationAnalyzer.cs deleted file mode 100644 index 0b8615d217..0000000000 --- a/Nitrox.Analyzers/Diagnostics/LocalizationAnalyzer.cs +++ /dev/null @@ -1,173 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Collections.Immutable; -using System.IO; -using System.Linq; -using System.Text.RegularExpressions; -using Microsoft.CodeAnalysis; -using Microsoft.CodeAnalysis.CSharp; -using Microsoft.CodeAnalysis.CSharp.Syntax; -using Microsoft.CodeAnalysis.Diagnostics; - -namespace Nitrox.Analyzers.Diagnostics; - -/// -/// Tests that requested localization keys exist in the English localization file. -/// -[DiagnosticAnalyzer(LanguageNames.CSharp)] -public sealed class LocalizationAnalyzer : DiagnosticAnalyzer -{ - public const string INVALID_LOCALIZATION_KEY_DIAGNOSTIC_ID = $"{nameof(LocalizationAnalyzer)}001"; - - private const string NITROX_LOCALIZATION_PREFIX = "Nitrox_"; - private static readonly string relativePathFromSolutionDirToEnglishLanguageFile = Path.Combine("Nitrox.Assets.Subnautica", "LanguageFiles", "en.json"); - private static readonly Regex localizationParseRegex = new(@"^\s*""([^""]+)""\s*:\s*""([^""]+)""", RegexOptions.Compiled | RegexOptions.Multiline); - - private static readonly DiagnosticDescriptor invalidLocalizationKeyRule = new(INVALID_LOCALIZATION_KEY_DIAGNOSTIC_ID, - "Tests localization usages are valid", - "Localization key '{0}' does not exist in '{1}'", - "Usage", - DiagnosticSeverity.Warning, - true, - "Tests that requested localization keys exist in the English localization file"); - - /// - /// Gets the list of rules of supported diagnostics. - /// - public override ImmutableArray SupportedDiagnostics => ImmutableArray.Create(invalidLocalizationKeyRule); - - /// - /// Initializes the analyzer by registering on symbol occurrence in the targeted code. - /// - public override void Initialize(AnalysisContext context) - { - context.ConfigureGeneratedCodeAnalysis(GeneratedCodeAnalysisFlags.None); - context.EnableConcurrentExecution(); - - context.RegisterCompilationStartAction(startContext => - { - IMethodSymbol languageGetMethodSymbol = startContext.Compilation.GetTypesByMetadataName("Language").FirstOrDefault(a => a.ContainingAssembly.Name.Equals("Assembly-Csharp", StringComparison.OrdinalIgnoreCase))?.GetMembers("Get").FirstOrDefault(m => m.Kind == SymbolKind.Method) as IMethodSymbol; - if (languageGetMethodSymbol == null) - { - return; - } - - startContext.Options.AnalyzerConfigOptionsProvider.GlobalOptions.TryGetValue("build_property.projectdir", out string projectDir); - if (LocalizationHelper.Load(projectDir)) - { - startContext.RegisterSyntaxNodeAction(c => AnalyzeStringNode(c, languageGetMethodSymbol), SyntaxKind.StringLiteralExpression); - } - }); - } - - /// - /// Analyzes string literals in code that are passed as argument to 'Language.main.Get'. - /// - private void AnalyzeStringNode(SyntaxNodeAnalysisContext context, IMethodSymbol languageGetMethodSymbol) - { - LiteralExpressionSyntax expression = (LiteralExpressionSyntax)context.Node; - if (expression.Parent is not ArgumentSyntax argument) - { - return; - } - if (argument.Parent is not { Parent: InvocationExpressionSyntax invocation }) - { - return; - } - if (context.SemanticModel.GetSymbolInfo(invocation).Symbol is not IMethodSymbol method) - { - return; - } - if (!SymbolEqualityComparer.Default.Equals(method, languageGetMethodSymbol)) - { - return; - } - // Ignore language call for non-nitrox keys. - string stringValue = expression.Token.ValueText; - if (!stringValue.StartsWith(NITROX_LOCALIZATION_PREFIX, StringComparison.OrdinalIgnoreCase)) - { - return; - } - if (LocalizationHelper.ContainsKey(stringValue)) - { - return; - } - context.ReportDiagnostic(Diagnostic.Create(invalidLocalizationKeyRule, context.Node.GetLocation(), stringValue, LocalizationHelper.FileName)); - } - - /// - /// Wrapper API for synchronized access to the English localization file. - /// - private static class LocalizationHelper - { - private static readonly object locker = new(); - private static string EnglishLocalizationFileName { get; set; } = ""; - private static ImmutableDictionary EnglishLocalization { get; set; } = ImmutableDictionary.Empty; - - public static bool IsEmpty - { - get - { - lock (locker) - { - return EnglishLocalization.IsEmpty; - } - } - } - - public static string FileName - { - get - { - lock (locker) - { - return EnglishLocalizationFileName; - } - } - } - - public static bool ContainsKey(string key) - { - lock (locker) - { - return EnglishLocalization.ContainsKey(key); - } - } - - public static bool Load(string projectDir) - { - if (string.IsNullOrWhiteSpace(projectDir)) - { - return false; - } - string solutionDir = Directory.GetParent(projectDir)?.Parent?.FullName; - if (!Directory.Exists(solutionDir)) - { - return false; - } - - string enJson; - lock (locker) - { - EnglishLocalizationFileName = Path.Combine(solutionDir, relativePathFromSolutionDirToEnglishLanguageFile); - if (!File.Exists(EnglishLocalizationFileName)) - { - return false; - } - - enJson = File.ReadAllText(EnglishLocalizationFileName); - } - // Parse localization JSON to dictionary for lookup. - Dictionary keyValue = new(); - foreach (Match match in localizationParseRegex.Matches(enJson)) - { - keyValue.Add(match.Groups[1].Value, match.Groups[2].Value); - } - lock (locker) - { - EnglishLocalization = keyValue.ToImmutableDictionary(); - } - return true; - } - } -} diff --git a/Nitrox.Analyzers/Diagnostics/StringUsageAnalyzer.cs b/Nitrox.Analyzers/Diagnostics/StringUsageAnalyzer.cs deleted file mode 100644 index 26cd375970..0000000000 --- a/Nitrox.Analyzers/Diagnostics/StringUsageAnalyzer.cs +++ /dev/null @@ -1,80 +0,0 @@ -using System.Collections.Immutable; -using Microsoft.CodeAnalysis; -using Microsoft.CodeAnalysis.CSharp; -using Microsoft.CodeAnalysis.CSharp.Syntax; -using Microsoft.CodeAnalysis.Diagnostics; - -namespace Nitrox.Analyzers.Diagnostics; - -[DiagnosticAnalyzer(LanguageNames.CSharp)] -public sealed class StringUsageAnalyzer : DiagnosticAnalyzer -{ - public const string PREFER_INTERPOLATED_STRING_DIAGNOSTIC_ID = $"{nameof(StringUsageAnalyzer)}001"; - - private static readonly DiagnosticDescriptor preferInterpolatedStringRule = new(PREFER_INTERPOLATED_STRING_DIAGNOSTIC_ID, - "Prefer interpolated string over string concat", - "String concat can be turned into interpolated string", - "Usage", - DiagnosticSeverity.Warning, - true, - "Prefer interpolated string over concatenating strings"); - - public override ImmutableArray SupportedDiagnostics => ImmutableArray.Create(preferInterpolatedStringRule); - - public override void Initialize(AnalysisContext context) - { - context.ConfigureGeneratedCodeAnalysis(GeneratedCodeAnalysisFlags.None); - context.EnableConcurrentExecution(); - - context.RegisterSyntaxNodeAction(AnalyzeAddNode, SyntaxKind.AddExpression); - } - - private void AnalyzeAddNode(SyntaxNodeAnalysisContext context) - { - bool IsPartOfStringConcat(SyntaxNode node) - { - switch (node) - { - case LiteralExpressionSyntax literal: - return literal.IsKind(SyntaxKind.StringLiteralExpression); - case InterpolatedStringExpressionSyntax: - return true; - case MemberAccessExpressionSyntax member: - string memberType = context.SemanticModel.GetTypeInfo(member).ConvertedType?.Name; - return memberType == "String"; - case BinaryExpressionSyntax binary: - // If one side is string-ish then the other side will get implicitly casted to string. - return binary.IsKind(SyntaxKind.AddExpression) && (IsPartOfStringConcat(binary.Right) || IsPartOfStringConcat(binary.Left)); - default: - return false; - } - } - - static bool IsLeftMostNodeInConcat(SyntaxNode node) - { - switch (node) - { - case BinaryExpressionSyntax: - case InterpolatedStringContentSyntax: - return false; - case ParenthesizedExpressionSyntax: - return IsLeftMostNodeInConcat(node.Parent); - } - return true; - } - - BinaryExpressionSyntax expression = (BinaryExpressionSyntax)context.Node; - // Deduplicate warnings. Only left most '+' of the expression should be handled here. - if (!IsLeftMostNodeInConcat(expression.Parent)) - { - return; - } - // Test if this should be interpolated. - if (!IsPartOfStringConcat(expression.Left) && !IsPartOfStringConcat(expression.Right)) - { - return; - } - - context.ReportDiagnostic(Diagnostic.Create(preferInterpolatedStringRule, expression.GetLocation(), expression)); - } -} diff --git a/Nitrox.Analyzers/Diagnostics/UnitySkippedObjectLifetimeAnalyzer.cs b/Nitrox.Analyzers/Diagnostics/UnitySkippedObjectLifetimeAnalyzer.cs deleted file mode 100644 index 26a6df3c29..0000000000 --- a/Nitrox.Analyzers/Diagnostics/UnitySkippedObjectLifetimeAnalyzer.cs +++ /dev/null @@ -1,123 +0,0 @@ -using System.Collections.Immutable; -using Microsoft.CodeAnalysis; -using Microsoft.CodeAnalysis.CSharp; -using Microsoft.CodeAnalysis.CSharp.Syntax; -using Microsoft.CodeAnalysis.Diagnostics; -using Nitrox.Analyzers.Extensions; - -namespace Nitrox.Analyzers.Diagnostics; - -/// -/// Test that Unity objects are properly checked for their lifetime. -/// The lifetime check is skipped when using "is null" or "obj?.member" as opposed to "== null". -/// -[DiagnosticAnalyzer(LanguageNames.CSharp)] -public sealed class UnitySkippedObjectLifetimeAnalyzer : DiagnosticAnalyzer -{ - public const string FIX_FUNCTION_NAME = "AliveOrNull"; - public const string FIX_FUNCTION_NAMESPACE = "NitroxClient.Unity.Helper"; - public const string CONDITIONAL_ACCESS_DIAGNOSTIC_ID = $"{nameof(UnitySkippedObjectLifetimeAnalyzer)}001"; - public const string IS_NULL_DIAGNOSTIC_ID = $"{nameof(UnitySkippedObjectLifetimeAnalyzer)}002"; - public const string NULL_COALESCE_DIAGNOSTIC_ID = $"{nameof(UnitySkippedObjectLifetimeAnalyzer)}003"; - private const string RULE_TITLE = "Tests that Unity object lifetime is not ignored"; - private const string RULE_DESCRIPTION = "Tests that Unity object lifetime checks are not ignored."; - - private static readonly DiagnosticDescriptor conditionalAccessRule = new(CONDITIONAL_ACCESS_DIAGNOSTIC_ID, - RULE_TITLE, - "'?.' is invalid on type '{0}' as it derives from 'UnityEngine.Object', bypassing the Unity object lifetime check", - "Usage", - DiagnosticSeverity.Error, - true, - RULE_DESCRIPTION); - - private static readonly DiagnosticDescriptor isNullRule = new(IS_NULL_DIAGNOSTIC_ID, - RULE_TITLE, - "'is null' is invalid on type '{0}' as it derives from 'UnityEngine.Object', bypassing the Unity object lifetime check", - "Usage", - DiagnosticSeverity.Error, - true, - RULE_DESCRIPTION); - - private static readonly DiagnosticDescriptor nullCoalesceRule = new(NULL_COALESCE_DIAGNOSTIC_ID, - RULE_TITLE, - "'??' is invalid on type '{0}' as it derives from 'UnityEngine.Object', bypassing the Unity object lifetime check", - "Usage", - DiagnosticSeverity.Error, - true, - RULE_DESCRIPTION); - - /// - /// Gets the list of rules of supported diagnostics. - /// - public override ImmutableArray SupportedDiagnostics => ImmutableArray.Create(conditionalAccessRule, isNullRule, nullCoalesceRule); - - /// - /// Initializes the analyzer by registering on symbol occurrence in the targeted code. - /// - public override void Initialize(AnalysisContext context) - { - context.ConfigureGeneratedCodeAnalysis(GeneratedCodeAnalysisFlags.None); - context.EnableConcurrentExecution(); - - context.RegisterCompilationStartAction(compStartContext => - { - INamedTypeSymbol unityObjectTypeSymbol = compStartContext.Compilation.GetTypeByMetadataName("UnityEngine.Object"); - if (unityObjectTypeSymbol == null) - { - return; - } - - compStartContext.RegisterSyntaxNodeAction(c => AnalyzeIsNullNode(c, unityObjectTypeSymbol), SyntaxKind.IsPatternExpression); - compStartContext.RegisterSyntaxNodeAction(c => AnalyzeConditionalAccessNode(c, unityObjectTypeSymbol), SyntaxKind.ConditionalAccessExpression); - compStartContext.RegisterSyntaxNodeAction(c => AnalyzeCoalesceNode(c, unityObjectTypeSymbol), SyntaxKind.CoalesceExpression); - }); - } - - private void AnalyzeIsNullNode(SyntaxNodeAnalysisContext context, ITypeSymbol unityObjectSymbol) - { - IsPatternExpressionSyntax expression = (IsPatternExpressionSyntax)context.Node; - // Is this a "is null" check? - if (expression.Pattern is not ConstantPatternSyntax constantPattern) - { - return; - } - if (constantPattern.Expression is not LiteralExpressionSyntax literal || !literal.Token.IsKind(SyntaxKind.NullKeyword)) - { - return; - } - // Is it on a UnityEngine.Object? - if (IsUnityObjectExpression(context, expression.Expression, unityObjectSymbol, out ITypeSymbol originSymbol)) - { - context.ReportDiagnostic(Diagnostic.Create(isNullRule, constantPattern.GetLocation(), originSymbol!.Name)); - } - } - - private void AnalyzeConditionalAccessNode(SyntaxNodeAnalysisContext context, ITypeSymbol unityObjectSymbol) - { - static bool IsFixedWithAliveOrNull(SyntaxNodeAnalysisContext context, ConditionalAccessExpressionSyntax expression) - { - return (context.SemanticModel.GetSymbolInfo(expression.Expression).Symbol as IMethodSymbol)?.Name == FIX_FUNCTION_NAME; - } - - ConditionalAccessExpressionSyntax expression = (ConditionalAccessExpressionSyntax)context.Node; - if (IsUnityObjectExpression(context, expression.Expression, unityObjectSymbol, out ITypeSymbol originSymbol) && !IsFixedWithAliveOrNull(context, expression)) - { - context.ReportDiagnostic(Diagnostic.Create(conditionalAccessRule, context.Node.GetLocation(), originSymbol!.Name)); - } - } - - private void AnalyzeCoalesceNode(SyntaxNodeAnalysisContext context, ITypeSymbol unityObjectSymbol) - { - BinaryExpressionSyntax expression = (BinaryExpressionSyntax)context.Node; - if (IsUnityObjectExpression(context, expression.Left, unityObjectSymbol, out ITypeSymbol originSymbol)) - { - context.ReportDiagnostic(Diagnostic.Create(nullCoalesceRule, context.Node.GetLocation(), originSymbol!.Name)); - } - } - - private bool IsUnityObjectExpression(SyntaxNodeAnalysisContext context, ExpressionSyntax possibleUnityAccessExpression, ITypeSymbol compareSymbol, out ITypeSymbol possibleUnitySymbol) - { - possibleUnitySymbol = context.SemanticModel.GetTypeInfo(possibleUnityAccessExpression).Type; - return possibleUnitySymbol.IsType(compareSymbol); - } -} diff --git a/Nitrox.Analyzers/Extensions/DebugExtensions.cs b/Nitrox.Analyzers/Extensions/DebugExtensions.cs deleted file mode 100644 index 8a3fe00265..0000000000 --- a/Nitrox.Analyzers/Extensions/DebugExtensions.cs +++ /dev/null @@ -1,43 +0,0 @@ -using System; -using System.Collections.Concurrent; -using System.Diagnostics; -using System.IO; -using System.Threading.Tasks; - -namespace Nitrox.Analyzers.Extensions; - -public static class DebugExtensions -{ - private static readonly string desktopPath = Environment.GetFolderPath(Environment.SpecialFolder.Desktop); - private static readonly ConcurrentQueue<(object source, string message)> logQueue = new(); - private static readonly object logLocker = new(); - - /// - /// Can be used to test analyzers. - /// - [Conditional("DEBUG")] - public static void Log(this object analyzer, string message) - { - if (analyzer == null) - { - return; - } - - logQueue.Enqueue((analyzer, message)); - Task.Run(() => - { - while (!logQueue.IsEmpty) - { - if (!logQueue.TryDequeue(out (object source, string message) pair)) - { - continue; - } - - lock (logLocker) - { - File.AppendAllText(Path.Combine(desktopPath, $"{pair.source.GetType().Name}.log"), pair.message + Environment.NewLine); - } - } - }); - } -} diff --git a/Nitrox.Analyzers/Extensions/SymbolExtensions.cs b/Nitrox.Analyzers/Extensions/SymbolExtensions.cs deleted file mode 100644 index 7ac60aee2e..0000000000 --- a/Nitrox.Analyzers/Extensions/SymbolExtensions.cs +++ /dev/null @@ -1,28 +0,0 @@ -using Microsoft.CodeAnalysis; - -namespace Nitrox.Analyzers.Extensions; - -public static class SymbolExtensions -{ - public static bool IsType(this ITypeSymbol symbol, SemanticModel semanticModel, string fullyQualifiedTypeName) - { - return symbol.IsType(semanticModel.Compilation.GetTypeByMetadataName(fullyQualifiedTypeName)); - } - - public static bool IsType(this ITypeSymbol symbol, ITypeSymbol targetingSymbol) - { - if (SymbolEqualityComparer.Default.Equals(symbol, targetingSymbol)) - { - return true; - } - while (symbol.BaseType is { } baseTypeSymbol) - { - symbol = baseTypeSymbol; - if (SymbolEqualityComparer.Default.Equals(symbol, targetingSymbol)) - { - return true; - } - } - return false; - } -} diff --git a/Nitrox.Analyzers/Fixers/UnitySkippedObjectLifetimeFixProvider.cs b/Nitrox.Analyzers/Fixers/UnitySkippedObjectLifetimeFixProvider.cs deleted file mode 100644 index b86e600d20..0000000000 --- a/Nitrox.Analyzers/Fixers/UnitySkippedObjectLifetimeFixProvider.cs +++ /dev/null @@ -1,70 +0,0 @@ -extern alias JB; -using System.Collections.Immutable; -using System.Composition; -using System.Linq; -using System.Threading; -using System.Threading.Tasks; -using JB::JetBrains.Annotations; -using Microsoft.CodeAnalysis; -using Microsoft.CodeAnalysis.CodeActions; -using Microsoft.CodeAnalysis.CodeFixes; -using Microsoft.CodeAnalysis.CSharp; -using Microsoft.CodeAnalysis.CSharp.Syntax; -using Microsoft.CodeAnalysis.Text; -using Nitrox.Analyzers.Diagnostics; -using static Microsoft.CodeAnalysis.CSharp.SyntaxFactory; - -namespace Nitrox.Analyzers.Fixers; - -[Shared] -[UsedImplicitly] -[ExportCodeFixProvider(LanguageNames.CSharp, Name = nameof(UnitySkippedObjectLifetimeFixProvider))] -public sealed class UnitySkippedObjectLifetimeFixProvider : CodeFixProvider -{ - private static readonly IdentifierNameSyntax aliveOrNull = IdentifierName(UnitySkippedObjectLifetimeAnalyzer.FIX_FUNCTION_NAME); - public override ImmutableArray FixableDiagnosticIds => ImmutableArray.Create(UnitySkippedObjectLifetimeAnalyzer.CONDITIONAL_ACCESS_DIAGNOSTIC_ID); - - public override FixAllProvider GetFixAllProvider() => WellKnownFixAllProviders.BatchFixer; - - public override async Task RegisterCodeFixesAsync(CodeFixContext context) - { - // Code template from: https://learn.microsoft.com/en-us/dotnet/csharp/roslyn-sdk/tutorials/how-to-write-csharp-analyzer-code-fix - SyntaxNode root = await context.Document.GetSyntaxRootAsync(context.CancellationToken) - .ConfigureAwait(false); - Diagnostic diagnostic = context.Diagnostics.First(); - TextSpan diagnosticSpan = diagnostic.Location.SourceSpan; - ConditionalAccessExpressionSyntax declaration = root!.FindToken(diagnosticSpan.Start).Parent!.AncestorsAndSelf() - .OfType() - .First(); - context.RegisterCodeFix( - CodeAction.Create( - equivalenceKey: UnitySkippedObjectLifetimeAnalyzer.CONDITIONAL_ACCESS_DIAGNOSTIC_ID, - title: "Insert AliveOrNull() before conditional access of UnityEngine.Object", - createChangedDocument: c => InsertAliveOrNullAsync(context.Document, declaration, c) - ), - diagnostic); - } - - private async Task InsertAliveOrNullAsync(Document document, ConditionalAccessExpressionSyntax declaration, CancellationToken cancellationToken) - { - SyntaxNode root = await document.GetSyntaxRootAsync(cancellationToken).ConfigureAwait(false); - if (root == null) - { - return document; - } - - // 1. Wrap expression with an invocation to AliveOrNull, this will cause AliveOrNull to be called before the conditional access. - InvocationExpressionSyntax wrappedExpression = InvocationExpression(MemberAccessExpression(SyntaxKind.SimpleMemberAccessExpression, declaration.Expression, aliveOrNull)); - SyntaxNode newDeclaration = declaration.ReplaceNode(declaration.Expression, wrappedExpression); - root = root!.ReplaceNode(declaration, newDeclaration); - // 2. Ensure using statement for extension method .AliveOrNull(). - // This is done after the "AliveOrNull" wrap because the declaration instance can't be found when root instance updates. - if (root is CompilationUnitSyntax compilationRoot && compilationRoot.Usings.All(u => u.Name.ToString() != UnitySkippedObjectLifetimeAnalyzer.FIX_FUNCTION_NAMESPACE)) - { - root = compilationRoot.AddUsings(UsingDirective(aliveOrNull)); - } - - // Replace the old document with the new. - return document.WithSyntaxRoot(root); - } -} diff --git a/Nitrox.Analyzers/Nitrox.Analyzers.csproj b/Nitrox.Analyzers/Nitrox.Analyzers.csproj deleted file mode 100644 index 5ddb136e10..0000000000 --- a/Nitrox.Analyzers/Nitrox.Analyzers.csproj +++ /dev/null @@ -1,22 +0,0 @@ - - - - - netstandard2.0 - - - - - - - - - - - diff --git a/Nitrox.Assets.Subnautica/LanguageFiles/af.json b/Nitrox.Assets.Subnautica/LanguageFiles/af.json index 6a1f5ec0ae..a5001cd21b 100644 --- a/Nitrox.Assets.Subnautica/LanguageFiles/af.json +++ b/Nitrox.Assets.Subnautica/LanguageFiles/af.json @@ -1,9 +1,5 @@ { "Nitrox_AddServer": "Voeg Server By", - "Nitrox_AddServerAdd": "Voeg By", - "Nitrox_AddServerHost": "Netwerk Gasheer:", - "Nitrox_AddServerName": "Naam:", - "Nitrox_AddServerPort": "Netwerk Poort:", "Nitrox_Cancel": "Kanselleer", "Nitrox_CommandNotAvailable": "Hierdie bevel is nie beskikbaar in Nitrox nie", "Nitrox_ConnectTo": "Konnekteer tot", @@ -17,8 +13,6 @@ "Nitrox_HideIp": "Steek IP adresse weg", "Nitrox_InvalidUserName": "Tik asseblief 'n korrekte speler naam in.\n\nDit kan geen spasie of twyfelagtige karakters insluit nie.\nAanvaarde karakters: A-Z a-z 0-9 _ . -\nLengte: [3, 25]", "Nitrox_Join": "Sluit aan", - "Nitrox_JoinServerFailed": "Kon nie by die server aansluit nie", - "Nitrox_JoinServerIpAddress": "Server IP Adres", "Nitrox_JoinServerPassword": "Wagwoord:", "Nitrox_JoinServerPasswordHeader": "Server wagwoord word vereis", "Nitrox_JoiningSession": "Besig Om By Multispeler Sessie Aan Te Sluit", @@ -28,7 +22,6 @@ "Nitrox_LostConnectionWarn": "Nie meer gekonnekteer tot die server", "Nitrox_Multiplayer": "Multispeler", "Nitrox_MultiplayerLoaded": "Multispeler kliënt gelaai…", - "Nitrox_PlayerColor": "Speler Kleur", "Nitrox_PlayerKicked": "Jy is geskop van die server af", "Nitrox_RejectedSessionPolicy": "Bespreking verwerp…", "Nitrox_RequestingSessionPolicy": "Besig om te vra vir sessie beleid informasie…", @@ -37,7 +30,6 @@ "Nitrox_SilencedChatNotif": "Geselskap nou verstom", "Nitrox_StartServer": "Begin you sessie eerste voordat jy by die self aangebiede wêreld aansluit", "Nitrox_StreamerSettings": "Streamer wyse", - "Nitrox_SubmitPassword": "Dien in", "Nitrox_SyncingWorld": "Besig om multispeler wêreld te sinchroniseer…", "Nitrox_UnableToConnect": "Kon nie die afgeleë server kontak by:", "Nitrox_Waiting": "Besig om in tou te wag…", diff --git a/Nitrox.Assets.Subnautica/LanguageFiles/bg.json b/Nitrox.Assets.Subnautica/LanguageFiles/bg.json index 0967ef424b..8c39a0a92c 100644 --- a/Nitrox.Assets.Subnautica/LanguageFiles/bg.json +++ b/Nitrox.Assets.Subnautica/LanguageFiles/bg.json @@ -1 +1,80 @@ -{} +{ + "Nitrox_AddServer": "Добави Сървър", + "Nitrox_BuildingDesyncDetected": "Сървърът откри десинхронизация със сградите на локалния клиент (отидете в настройките на Nitrox, за да поискате ресинхронизация)", + "Nitrox_BuildingSettings": "Базова сграда", + "Nitrox_Cancel": "Отказ", + "Nitrox_CommandNotAvailable": "Тази команда не е налична в Nitrox", + "Nitrox_ConnectTo": "Свържи се със", + "Nitrox_DisconnectedSession": "Връзката със сървъра бе прекъсната", + "Nitrox_DiscordAccept": "Приемам", + "Nitrox_DiscordDecline": "Отказвам", + "Nitrox_DiscordInGame": "Играе като {PLAYER}", + "Nitrox_DiscordInGameState": "Гмурка се в бездната", + "Nitrox_DiscordMainMenuState": "Спотайва се в менюто", + "Nitrox_DiscordMultiplayerMenu": "Моля натиснете на Mултиплейър бутона в Главното Меню ако искате да влезете в сесия", + "Nitrox_DiscordPressToFocus": "Натисни за да отключиш", + "Nitrox_DiscordRequestText": "Поиска да се присъедини към твоята сесия", + "Nitrox_EnterName": "Въведете името на играча", + "Nitrox_ErrorDesyncDetected": "[Безопасна Сграда] Тази база е десинхронизирана, затова неможете да правите промени освен ако не ресинхронизирате сгради (в настройките на Nitrox)", + "Nitrox_ErrorRecentBuildUpdate": "Не можете да модифицирате база която е била наскоро променена от друг играч", + "Nitrox_Failure": "Възникна грешка", + "Nitrox_FinishedResyncRequest": "Отне {TIME}ms за ресинхронизирането на {COUNT} обекта", + "Nitrox_FirewallInterfering": "Изглежда всякаш настройките на твоята защитна стена пречат", + "Nitrox_HideIp": "Скриване на IP адресите", + "Nitrox_HidePing": "Скрий Пинг", + "Nitrox_IntroUWEPresents": "UNKNOWN WORLDS ENTERTAINMENT\n&\nNITROX ОТБОРА\n\nПРЕДСТАВЯТ", + "Nitrox_IntroWaitingPartner": "Изчакване за влизане на играч\n\nНатиснете {0}, за да пропуснете чакането", + "Nitrox_InvalidUserName": "Моля въведете валидно име на играча.\n\nНе трябва да съдържа разтояния или забранени символи\nПозволени символи: A-Z a-z 0-9 _ . -\nДължина: [3, 25]", + "Nitrox_Join": "Влез", + "Nitrox_JoinServerPassword": "Парола:", + "Nitrox_JoinServerPasswordHeader": "Сървъра изисква парола", + "Nitrox_JoiningSession": "Присъединяване в Мултиплейър Сесия", + "Nitrox_Kick": "Изгони {PLAYER}", + "Nitrox_KickQuestion": "Изгони {PLAYER}?", + "Nitrox_LaunchGame": "Стартиране на играта…", + "Nitrox_LoadingScreenWarn": "Очаквайте бъгове които могат да повредят играта", + "Nitrox_LostConnection": "Загубена връзка със игралния сървър", + "Nitrox_LostConnectionWarn": "Вече не сте свързани със сървъра", + "Nitrox_Multiplayer": "Мултиплейър", + "Nitrox_MultiplayerLoaded": "Мултиплейър клиент зареден…", + "Nitrox_Mute": "Заглуши {PLAYER}", + "Nitrox_MuteQuestion": "Заглуши {PLAYER}?", + "Nitrox_MutedPlayer": "{PLAYER} беше Заглушен", + "Nitrox_OutOfDateClient": "Вашата Nitrox инсталация е остаряла. Сървър: {serverVersion}, Ваш: {localVersion}.", + "Nitrox_OutOfDateServer": "Сървъра работи с по-стара версия на Nitrox. Поискайте администратора да актуализира съвъра или минете на по-стара Nitrox версия. Сървър: {serverVersion}, Ваш: {localVersion}.", + "Nitrox_PlayerDied": "{PLAYER} умря", + "Nitrox_PlayerDisconnected": "{PLAYER} напусна", + "Nitrox_PlayerJoined": "{PLAYER} се присъедини към играта.", + "Nitrox_PlayerKicked": "Вие бяхте изгонени от сървъра", + "Nitrox_PlayerLeft": "{PLAYER} напусна играта.", + "Nitrox_PlayerListTabName": "Списък с Играчи", + "Nitrox_RejectedSessionPolicy": "Резервацията е отхвърлена…", + "Nitrox_RemotePlayerObstacle": "Друг играч се намира вътре или в близост до деконструируем обект.", + "Nitrox_RequestingSessionPolicy": "Искане на информация за правилата на сесията…", + "Nitrox_ResyncBuildings": "Ресинхронизиране на базови сгради", + "Nitrox_ResyncOnCooldown": "Трябва да изчакате {TIME_LEFT} секунди, за да изпратите друго изискване за ресинхронизация", + "Nitrox_ResyncRequested": "Изпратена е заявка за ресинхронициране на бази", + "Nitrox_ResyncSettings": "Ресинхронизация", + "Nitrox_SafeBuilding": "Безопасна сграда", + "Nitrox_SafeBuildingLog": "Безопасна сграда логове", + "Nitrox_ServerStopped": "Сървърът е спрян", + "Nitrox_ShowPing": "Покажи Пинг", + "Nitrox_SilenceChat": "Заглушаване на чата", + "Nitrox_SilencedChatNotif": "Чатът беше заглушен", + "Nitrox_StartServer": "Първо стартирайте сървъра си, за да се присъедините към своя самостоятелно хостван свят", + "Nitrox_StreamerSettings": "Режим за стриймър", + "Nitrox_SyncingWorld": "Синхронизиране на мултиплейър света…", + "Nitrox_TeleportTo": "Телепортиране до {PLAYER}", + "Nitrox_TeleportToMe": "Телепортирай {PLAYER} до мен", + "Nitrox_TeleportToMeQuestion": "Телепортирай {PLAYER} до мен ?", + "Nitrox_TeleportToQuestion": "Телепортирай до {PLAYER}?", + "Nitrox_ThankForPlaying": "Благодарим ви, че използвате Nitrox!", + "Nitrox_UnableToConnect": "Невъзможно е да се свържете с отдалечения сървър на адрес:", + "Nitrox_Unmute": "Включване на звука на {PLAYER}", + "Nitrox_UnmuteQuestion": "Включете звука на {PLAYER}?", + "Nitrox_UnmutedPlayer": "Звука на {PLAYER} беше включен", + "Nitrox_Waiting": "Изчакване в опашката за присъединяване…", + "Nitrox_WaitingPassword": "Изчакване за въвеждане на парола на сървъра…", + "Nitrox_WaitingUserInput": "Изчакване на въвеждане от потребителя…", + "Nitrox_WorldSettling": "В очакване на уреждане на света…" +} diff --git a/Nitrox.Assets.Subnautica/LanguageFiles/ca.json b/Nitrox.Assets.Subnautica/LanguageFiles/ca.json new file mode 100644 index 0000000000..502dc614bd --- /dev/null +++ b/Nitrox.Assets.Subnautica/LanguageFiles/ca.json @@ -0,0 +1,53 @@ +{ + "Nitrox_AddServer": "Afegir Servidor", + "Nitrox_BuildingDesyncDetected": "El servidor ha detectat una desincronització amb els edificis del client local (ves a la configuració de Nitrox i sol·licita una resincronització)", + "Nitrox_BuildingSettings": "Construcció de base", + "Nitrox_Cancel": "Cancel·lar", + "Nitrox_CommandNotAvailable": "Aquesta comanda no esta disponible a Nitrox", + "Nitrox_ConnectTo": "Connectar a", + "Nitrox_DisconnectedSession": "Desconnectat del servidor", + "Nitrox_DiscordAccept": "Acceptar", + "Nitrox_DiscordDecline": "Refusar", + "Nitrox_DiscordInGame": "Jugant com a {PLAYER}", + "Nitrox_DiscordInGameState": "Capbussant-te a l'abisme", + "Nitrox_DiscordMainMenuState": "Amagat al menu", + "Nitrox_DiscordMultiplayerMenu": "Si us plau, prem el botó Multijugador en el menú principal si vols unir-te a una partida", + "Nitrox_DiscordPressToFocus": "Prem per desbloquejar", + "Nitrox_DiscordRequestText": "Ha demanat unir-se a la teva partida", + "Nitrox_EnterName": "Escriu el teu nom de jugador", + "Nitrox_ErrorDesyncDetected": "[Construcció Segura] Aquesta base esta desincronitzada i no la pots modificar fins que no resincronitzis edificis (a la configuració de Nitrox)", + "Nitrox_ErrorRecentBuildUpdate": "No es pot modificar una base que ha estat actualitzada recentment per un altre jugador", + "Nitrox_Failure": "Hi ha hagut un error", + "Nitrox_FinishedResyncRequest": "S'ha trigat {TIME}ms a resincronitzar {COUNT} entitats", + "Nitrox_FirewallInterfering": "Sembla que la configuració de teu tallafocs està interferint", + "Nitrox_HideIp": "Amaga adreces IP", + "Nitrox_HidePing": "Amaga la latència", + "Nitrox_IntroUWEPresents": "UNKNOWN WORLDS ENTERTAINMENT\n&\nL'EQUIP DE NITROX\n\nPRESENTEN", + "Nitrox_IntroWaitingPartner": "Esperant que un company s'uneixi\n\nPrem {0} per evitar l'espera", + "Nitrox_InvalidUserName": "Si us plau, escriu un nom de jugador valid.\n\nNo pot contenir cap espai o caràcters dubtosos\nCaràcters permesos: A-Z a-z 0-9 _.-\nLlargada: [3,25]", + "Nitrox_Join": "Uneix-te", + "Nitrox_JoinServerPassword": "Contrassenya:", + "Nitrox_JoinServerPasswordHeader": "Cal la contrassenya del servidor", + "Nitrox_JoiningSession": "Unint-se a Sessió Multijugador", + "Nitrox_Kick": "Expulsar a {PLAYER}", + "Nitrox_KickQuestion": "Expulsar a {PLAYER}?", + "Nitrox_LaunchGame": "Iniciant joc…", + "Nitrox_LoadingScreenWarn": "Espereu errors que trenquin el joc", + "Nitrox_LostConnection": "S'ha perdut la connexió al servidor del joc", + "Nitrox_LostConnectionWarn": "Ja no estàs connectat al servidor", + "Nitrox_Multiplayer": "Multijugador", + "Nitrox_MultiplayerLoaded": "Client multijugador carregat…", + "Nitrox_Mute": "Silencia a {PLAYER}", + "Nitrox_MuteQuestion": "Silenciar a {PLAYER}?", + "Nitrox_MutedPlayer": "S'ha silenciat a {PLAYER}", + "Nitrox_OutOfDateClient": "La teva instal·lació de Nitrox està obsoleta. Servidor: {serverVersion}, la teva: {localVersion}.", + "Nitrox_OutOfDateServer": "El servidor utilitza una versió més antiga de Nitrox. Demana a l'administrador del servidor que actualitzi el servidor o redueix la teva instal·lació de Nitrox. Servidor: {serverVersion}, tu: {localVersion}.", + "Nitrox_PlayerDied": "{PLAYER} ha mort", + "Nitrox_PlayerDisconnected": "{PLAYER} s'ha desconnectat", + "Nitrox_PlayerJoined": "{PLAYER} ha entrat al joc.", + "Nitrox_PlayerKicked": "Has estat expulsat del servidor", + "Nitrox_PlayerLeft": "{PLAYER} ha sortit del joc.", + "Nitrox_PlayerListTabName": "Llista de jugadors", + "Nitrox_RejectedSessionPolicy": "Reserva refusada…", + "Nitrox_RemotePlayerObstacle": "Un altre jugador esta a dintre o massa a prop de l'objectiu deconstructible." +} diff --git a/Nitrox.Assets.Subnautica/LanguageFiles/cs.json b/Nitrox.Assets.Subnautica/LanguageFiles/cs.json index 18a615df5a..b8b553acc4 100644 --- a/Nitrox.Assets.Subnautica/LanguageFiles/cs.json +++ b/Nitrox.Assets.Subnautica/LanguageFiles/cs.json @@ -1,46 +1,65 @@ { "Nitrox_AddServer": "Přidat Server", - "Nitrox_AddServerAdd": "Přidat", - "Nitrox_AddServerHost": "Host:", - "Nitrox_AddServerName": "Jméno:", - "Nitrox_AddServerPort": "Port:", + "Nitrox_BuildingDesyncDetected": "Server detekoval desynchronizaci s budovami lokálního klienta (přejděte do nastavení Nitroxu a požádejte o opětovnou synchronizaci)", + "Nitrox_BuildingSettings": "Budova základny", "Nitrox_Cancel": "Zrušit", "Nitrox_CommandNotAvailable": "Tento příkaz není dostupný v Nitroxu", - "Nitrox_ConnectTo": "Připojit se na", + "Nitrox_Confirm": "Potrvdit", + "Nitrox_ConnectTo": "Připojit se k", "Nitrox_DisconnectedSession": "Odpojen ze serveru", "Nitrox_DiscordAccept": "Přijmout", "Nitrox_DiscordDecline": "Odmítnout", + "Nitrox_DiscordInGame": "Hraje jako {PLAYER}", + "Nitrox_DiscordInGameState": "Potápění do propasti", + "Nitrox_DiscordMainMenuState": "Neaktivní v menu", + "Nitrox_DiscordMultiplayerMenu": "Pokud se chcete připojit k relaci, stiskněte tlačítko Více hráčů v hlavním menu", "Nitrox_DiscordPressToFocus": "Stiskni pro odemčení", "Nitrox_DiscordRequestText": "Požádán k připojení do tvé hry", "Nitrox_EnterName": "Jméno Hráče", + "Nitrox_Failure": "Nastala chyba", "Nitrox_FirewallInterfering": "Vypadá to že nastavení vaší brány firewall je nesprávné", "Nitrox_HideIp": "Skrýt IP adresu", + "Nitrox_HidePing": "Skrýt rychlost připojení", "Nitrox_InvalidUserName": "Prosím vložte platné hráčské jméno !\n\nNesmí obsahovat žádnou mezeru nebo pochybné znaky\nPovolené znaky: A-Z a-z 0-9 _ . -\nDélka : [3, 25]", "Nitrox_Join": "Připojit se", - "Nitrox_JoinServerFailed": "Nepodařilo se připojit k serveru", - "Nitrox_JoinServerIpAddress": "IP Serveru", "Nitrox_JoinServerPassword": "Heslo:", "Nitrox_JoinServerPasswordHeader": "Server vyžaduje heslo", "Nitrox_JoiningSession": "Připojování k serveru", + "Nitrox_Kick": "Vyhodit {PLAYER}", + "Nitrox_KickQuestion": "Vyhodit {PLAYER}?", "Nitrox_LaunchGame": "Spouštení hry…", "Nitrox_LoadingScreenWarn": "Očekávejte herní chyby které mohou kazit hru", "Nitrox_LostConnection": "Připojení k serveru ztraceno", "Nitrox_LostConnectionWarn": "Již nepřipojen k serveru", "Nitrox_Multiplayer": "Multiplayer", "Nitrox_MultiplayerLoaded": "Multiplayerový klient načten…", - "Nitrox_PlayerColor": "Barva Hráče", + "Nitrox_Mute": "Ztlumit {PLAYER}", + "Nitrox_MuteQuestion": "Ztlumit {PLAYER}?", + "Nitrox_MutedPlayer": "Ztlumený {PLAYER}", + "Nitrox_PlayerJoined": "{PLAYER} se připojil ke hře.", "Nitrox_PlayerKicked": "Byl jsi vyhozen ze serveru", + "Nitrox_PlayerLeft": "{PLAYER} opustil hru.", + "Nitrox_PlayerListTabName": "Seznam hráčů", "Nitrox_RejectedSessionPolicy": "Rezervace odmítnuta…", + "Nitrox_RemotePlayerObstacle": "Jiný hráč je buď uvnitř, nebo příliš blízko dekonstruovatelného cíle.", "Nitrox_RequestingSessionPolicy": "Požadování informací o stávající relaci…", "Nitrox_ServerStopped": "Server byl zastaven", + "Nitrox_ShowPing": "Zobrazit rychlost připojení", "Nitrox_SilenceChat": "Tichý chat", "Nitrox_SilencedChatNotif": "Chat je nyní tichý", "Nitrox_StartServer": "Pro připojení na vlastní hostovaný svět je potřeba zapnout server", "Nitrox_StreamerSettings": "Režim streamování", - "Nitrox_SubmitPassword": "Potvrdit", "Nitrox_SyncingWorld": "Synchronizování Multiplayerového Světa…", + "Nitrox_TeleportTo": "Teleportovat na {PLAYER}", + "Nitrox_TeleportToMe": "Teleportovat {PLAYER} ke mně", + "Nitrox_TeleportToMeQuestion": "Teleportovat {PLAYER} ke mě ?", + "Nitrox_TeleportToQuestion": "Teleportovat k {PLAYER}?", + "Nitrox_ThankForPlaying": "Děkujeme, že používáte Nitrox!", "Nitrox_UnableToConnect": "Nepodařilo se kontaktovat vzdálený server na:", - "Nitrox_Waiting": "Čekání ve frontě připojení…", + "Nitrox_Unmute": "Zrušit ztlumení pro {PLAYER}", + "Nitrox_UnmuteQuestion": "Zrušit ztlumení pro {PLAYER}?", + "Nitrox_UnmutedPlayer": "Neztlumený {PLAYER}", + "Nitrox_Waiting": "Čekání ve frontě na připojení…", "Nitrox_WaitingPassword": "Čekání na zadání serverového hesla…", "Nitrox_WaitingUserInput": "Čekání na uživatelský vstup…", "Nitrox_WorldSettling": "Čekání na načtení světa…" diff --git a/Nitrox.Assets.Subnautica/LanguageFiles/da.json b/Nitrox.Assets.Subnautica/LanguageFiles/da.json index b065272334..ea7269a730 100644 --- a/Nitrox.Assets.Subnautica/LanguageFiles/da.json +++ b/Nitrox.Assets.Subnautica/LanguageFiles/da.json @@ -1,45 +1,74 @@ { "Nitrox_AddServer": "Tilføj server", - "Nitrox_AddServerAdd": "Tilføj", - "Nitrox_AddServerHost": "Host:", - "Nitrox_AddServerName": "Navn:", - "Nitrox_AddServerPort": "Port:", + "Nitrox_BuildingDesyncDetected": "Server fandt en desynk med den lokale klients bygninger ( gå til nitrox indstillinger for at anmode om et resynk)", + "Nitrox_BuildingSettings": "Base bygning", "Nitrox_Cancel": "Annuller", "Nitrox_CommandNotAvailable": "Denne kommando er ikke tilgængelig i Nitrox", + "Nitrox_Confirm": "Bekræft", "Nitrox_ConnectTo": "Forbind til", + "Nitrox_DenyOwnershipHand": "En anden spiller interagerer allerede med dette projekt", "Nitrox_DisconnectedSession": "Afbrudt fra server", "Nitrox_DiscordAccept": "Accepter", "Nitrox_DiscordDecline": "Afvis", + "Nitrox_DiscordInGame": "spiller som {PLAYER}", + "Nitrox_DiscordInGameState": "Dykker ned i afgrunden", + "Nitrox_DiscordMainMenuState": "Lurer i menuen", + "Nitrox_DiscordMultiplayerMenu": "vær sød at klikke på Multiplayer knappen på hoved menuen hvis du gerne vil tilstlutte dig sessionen", "Nitrox_DiscordPressToFocus": "Tryk for at låse op", "Nitrox_DiscordRequestText": "Vil gerne spille med", "Nitrox_EnterName": "Spillernavn", + "Nitrox_Failure": "der skete en fejl", "Nitrox_FirewallInterfering": "Det ser ud til, at dine firewallindstillinger forstyrrer", "Nitrox_HideIp": "Skjul IP-adresser", + "Nitrox_HidePing": "gem ping", "Nitrox_InvalidUserName": "Indtast venligst et gyldigt navn!\n\n Det må ikke indeholde mellemrum eller tvivlsomme tegn\n Tilladte tegn : A-Z a-z 0-9 _ . -\nLængde : [3, 25]", "Nitrox_Join": "Deltag", - "Nitrox_JoinServerFailed": "Kunne ikke forbinde til serveren", - "Nitrox_JoinServerIpAddress": "Server IP", "Nitrox_JoinServerPassword": "Adgangskode:", "Nitrox_JoinServerPasswordHeader": "Server adgangskode påkrævet", "Nitrox_JoiningSession": "Deltager i spil", + "Nitrox_Kick": "Smid {PLAYER} ud", + "Nitrox_KickQuestion": "Smid {PLAYER} ud?", "Nitrox_LaunchGame": "Starter spil…", "Nitrox_LoadingScreenWarn": "Forvent spil-ødelæggene fejl", "Nitrox_LostConnection": "Mistede forbindelsen til serveren", "Nitrox_LostConnectionWarn": "Er ikke længere forbundet", "Nitrox_Multiplayer": "Multiplayer", "Nitrox_MultiplayerLoaded": "Multiplayer-klient indlæst…", - "Nitrox_PlayerColor": "Spillerfarve", + "Nitrox_Mute": "Stum {PLAYER}", + "Nitrox_MuteQuestion": "stum {PLAYER}?", + "Nitrox_MutedPlayer": "dæmpet {PLAYER}", + "Nitrox_OutOfDateClient": "Din Nitrox installation er forældet. Server: {serverVersion}, din: {localVersion}.", + "Nitrox_OutOfDateServer": "Serveren bruger en ældre version af Nitrox. Bed administratoren om at opgradere serveren til nyeste version, eller nedgrader din egen Nitrox installation. Server: {serverVersion}, din: {localVersion}.", + "Nitrox_PlayerDied": "{PLAYER} døde", + "Nitrox_PlayerDisconnected": "{PLAYER} koblet fra", + "Nitrox_PlayerJoined": "{PLAYER} deltog i spillet.", "Nitrox_PlayerKicked": "Du er blevet smidt ud fra serveren", + "Nitrox_PlayerLeft": "{PLAYER} forlod spillet.", + "Nitrox_PlayerListTabName": "spillerliste", "Nitrox_RejectedSessionPolicy": "Reservation afvist…", - "Nitrox_RequestingSessionPolicy": "Anmoder om serverens spil information", + "Nitrox_RemotePlayerObstacle": "En anden spiller er enten inde i eller for tæt på det dekonstruerbare mål.", + "Nitrox_RequestingSessionPolicy": "Anmoder om serverens spil information…", + "Nitrox_ResyncBuildings": "Gensynkroniser base bygninger", + "Nitrox_ResyncRequested": "Igangsatte en gensynkroniserings anmodning for baser", + "Nitrox_ResyncSettings": "Gensynkronisering", + "Nitrox_SafeBuilding": "Sikker konstruktion", + "Nitrox_SafeBuildingLog": "Sikker konstruktions log", "Nitrox_ServerStopped": "Serveren er stoppet", + "Nitrox_ShowPing": "Vis Ping", "Nitrox_SilenceChat": "Slå chat fra", "Nitrox_SilencedChatNotif": "Chat er nu slået fra", "Nitrox_StartServer": "Start din server først for at deltage i din selvhostede verden", "Nitrox_StreamerSettings": "Streamer-tilstand", - "Nitrox_SubmitPassword": "Forbind", "Nitrox_SyncingWorld": "Synkronisere multiplayer verden…", + "Nitrox_TeleportTo": "Teleporter til {PLAYER}", + "Nitrox_TeleportToMe": "Teleporter {PLAYER} til mig", + "Nitrox_TeleportToMeQuestion": "Teleporter {PLAYER} til mig?", + "Nitrox_TeleportToQuestion": "Teleporter til {PLAYER}?", + "Nitrox_ThankForPlaying": "Tak fordi du bruger Nitrox!", "Nitrox_UnableToConnect": "Kan ikke kontakte den eksterne server på:", + "Nitrox_Unmute": "Slå {PLAYER}'s lyd til", + "Nitrox_UnmuteQuestion": "Slå {PLAYER}'s lyd til?", + "Nitrox_UnmutedPlayer": "{PLAYER}'s lyd blev slået til", "Nitrox_Waiting": "Venter i forbindelseskøen…", "Nitrox_WaitingPassword": "Venter på serveradgangskode…", "Nitrox_WaitingUserInput": "Venter på brugerens input…", diff --git a/Nitrox.Assets.Subnautica/LanguageFiles/de.json b/Nitrox.Assets.Subnautica/LanguageFiles/de.json index 53f72e38a2..2a838765e5 100644 --- a/Nitrox.Assets.Subnautica/LanguageFiles/de.json +++ b/Nitrox.Assets.Subnautica/LanguageFiles/de.json @@ -1,12 +1,12 @@ { "Nitrox_AddServer": "Server hinzufügen", - "Nitrox_AddServerAdd": "Hinzufügen", - "Nitrox_AddServerHost": "Host:", - "Nitrox_AddServerName": "Name:", - "Nitrox_AddServerPort": "Port:", + "Nitrox_BuildingDesyncDetected": "Der Server hat Synchronisierungsfehler in den lokalen Basen entdeckt. Gehe in die Nitrox Einstellungen um eine Resynchronisierung anzufordern", + "Nitrox_BuildingSettings": "Basen-Bau", "Nitrox_Cancel": "Abbrechen", "Nitrox_CommandNotAvailable": "Dieser Befehl ist in Nitrox nicht verfügbar", + "Nitrox_Confirm": "Bestätigen", "Nitrox_ConnectTo": "Verbinden mit", + "Nitrox_DenyOwnershipHand": "Ein andere Spieler interagiert gerade mit diesem Objekt", "Nitrox_DisconnectedSession": "Die Verbindung zum Server wurde unterbrochen", "Nitrox_DiscordAccept": "Akzeptieren", "Nitrox_DiscordDecline": "Ablehnen", @@ -17,16 +17,21 @@ "Nitrox_DiscordPressToFocus": "Drücke zum Interagieren", "Nitrox_DiscordRequestText": "Erbittet deinem Server beizutreten", "Nitrox_EnterName": "Geben Sie Ihren Spielernamen ein", + "Nitrox_ErrorDesyncDetected": "[Sicherer Basen-Bau] Diese Basis ist aktuell desynchronisiert und dadurch nicht änderbar bis sie resynchronisiert wurde (siehe Nitrox Einstellungen)", + "Nitrox_ErrorRecentBuildUpdate": "Modifizierung der Basis ist nicht möglich da sie neulich von einem anderen Spieler geändert wurde", "Nitrox_Failure": "Ein Fehler ist aufgetreten", + "Nitrox_FinishedResyncRequest": "Es benötigte {TIME}ms um {COUNT} Einheiten zu resynchronisieren", "Nitrox_FirewallInterfering": "Es scheint als ob Firewall Einstellungen die Verbindung blockieren", "Nitrox_HideIp": "IPs verstecken", - "Nitrox_HidePing": "Signal verstecken", + "Nitrox_HidePing": "Ping verstecken", + "Nitrox_IntroUWEPresents": "UNKNOWN WORLDS ENTERTAINMENT\n&\nDAS NITROX-TEAM\n\nPRÄSENTIEREN", + "Nitrox_IntroWaitingPartner": "Es wird darauf gewartet das ein Partner beitritt\n\nDrücke die {0}-Taste um das Warten abzubrechen", "Nitrox_InvalidUserName": "Bitte gebe einen validen Spielernamen ein.\n\nDieser darf kein Leerzeichen oder andere invalide Zeichen beinhalten\nErlaubte Zeichen : A-Z a-z 0-9 _ . -\nLänge: [3, 25]", "Nitrox_Join": "Beitreten", - "Nitrox_JoinServerFailed": "Die Verbindung zum Server ist gescheitert", - "Nitrox_JoinServerIpAddress": "Server IP", + "Nitrox_JoinServer": "Beitreten:", "Nitrox_JoinServerPassword": "Passwort:", "Nitrox_JoinServerPasswordHeader": "Serverpasswort benötigt", + "Nitrox_JoinServerPlaceholder": "Bitte geben sie das Server Passwort ein", "Nitrox_JoiningSession": "Betrete Mehrspieler-Welt", "Nitrox_Kick": "{PLAYER} entfernen", "Nitrox_KickQuestion": "Wollen Sie {PLAYER} entfernen?", @@ -34,23 +39,36 @@ "Nitrox_LoadingScreenWarn": "Spiel brechende Fehler sind zu erwarten", "Nitrox_LostConnection": "Die Verbindung zum Spiel-Server wurde unterbrochen", "Nitrox_LostConnectionWarn": "Nicht länger Verbunden mit dem Server", + "Nitrox_MissingPermission": "Du hast keine Berechtigung diesen Befehl auszuführen [{PERMISSION}]", "Nitrox_Multiplayer": "Mehrspieler", "Nitrox_MultiplayerLoaded": "Mehrspieler-Anwendung wurde gestartet…", "Nitrox_Mute": "{PLAYER} stumm schalten", "Nitrox_MuteQuestion": "Wollen Sie {PLAYER} stumm schalten?", "Nitrox_MutedPlayer": "{PLAYER} wurde stumm geschaltet", - "Nitrox_PlayerColor": "Spieler Farbe", + "Nitrox_OK": "Ok", + "Nitrox_OutOfDateClient": "Ihre Nitrox Installation ist nicht mehr aktuell. Server: {serverVersion}, Ihre: {localVersion}.", + "Nitrox_OutOfDateServer": "Der Server läuft mit einer älteren Version von Nitrox. Fragen Sie den Administrator den Server zu aktualisieren oder stufe deine Nitrox Installation zurück. Server: {serverVersion}, Ihre: {localVersion}.", + "Nitrox_PlayerDied": "{PLAYER} ist gestorben", + "Nitrox_PlayerDisconnected": "{PLAYER} hat die Verbindung getrennt", + "Nitrox_PlayerJoined": "{PLAYER} ist dem Spiel beigetreten.", "Nitrox_PlayerKicked": "Du wurdest vom Server geworfen", + "Nitrox_PlayerLeft": "{PLAYER} hat das Spiel verlassen.", "Nitrox_PlayerListTabName": "Spieler Liste", "Nitrox_RejectedSessionPolicy": "Anfrage wurde abgelehnt…", + "Nitrox_RemotePlayerObstacle": "In Benutzung von einem anderen Spieler oder zu nah an einem zerstörbarem Ziel.", "Nitrox_RequestingSessionPolicy": "Frage nach Informationen zu den Sitzungsrichtlinien…", + "Nitrox_ResyncBuildings": "Synchronisiere Basen neu", + "Nitrox_ResyncOnCooldown": "Sie müssen noch {TIME_LEFT} Sekunden warten um einen neuen Resynchronisierung-Antrag zu senden", + "Nitrox_ResyncRequested": "Eine Basen-Resynchronisierung-Antrag wurde übermittelt", + "Nitrox_ResyncSettings": "Resynchronisierung", + "Nitrox_SafeBuilding": "Sicheres bauen", + "Nitrox_SafeBuildingLog": "Sicheres bauen protokollieren", "Nitrox_ServerStopped": "Der Server wurde gestoppt", "Nitrox_ShowPing": "Signal anzeigen", "Nitrox_SilenceChat": "Chat stumm schalten", "Nitrox_SilencedChatNotif": "Chat ist nun stumm geschaltet", "Nitrox_StartServer": "Bitte starte zuerst den Server um deine selbst gehostete Welt zu betreten", "Nitrox_StreamerSettings": "Streamer Einstellungen", - "Nitrox_SubmitPassword": "Bestätigen", "Nitrox_SyncingWorld": "Synchronisiere Mehrspieler-Welt…", "Nitrox_TeleportTo": "Zu {PLAYER} teleportieren", "Nitrox_TeleportToMe": "{PLAYER} zu mir teleportieren", diff --git a/Nitrox.Assets.Subnautica/LanguageFiles/el.json b/Nitrox.Assets.Subnautica/LanguageFiles/el.json index 1ce6d4cd49..b7550677e7 100644 --- a/Nitrox.Assets.Subnautica/LanguageFiles/el.json +++ b/Nitrox.Assets.Subnautica/LanguageFiles/el.json @@ -1,45 +1,79 @@ { "Nitrox_AddServer": "Προσθήκη διακομιστή", - "Nitrox_AddServerAdd": "Πρόσθεσε", - "Nitrox_AddServerHost": "Kεντρικός Διακομιστής:", - "Nitrox_AddServerName": "'Ονομα:", - "Nitrox_AddServerPort": "Θύρα διακομιστή:", + "Nitrox_BuildingDesyncDetected": "Ο διακομιστής εντόπισε αποσυγχρονισμό των δομών του τοπικού χρήστη (μεταβείτε στις ρυθμίσεις Nitrox για να ζητήσετε επανασυγχρονισμό)", + "Nitrox_BuildingSettings": "Δομή Βάσης", "Nitrox_Cancel": "Άκυρο", "Nitrox_CommandNotAvailable": "Αυτή η εντολή δεν είναι διαθέσιμη στο Nitrox", "Nitrox_ConnectTo": "Σύνδεση με", + "Nitrox_DenyOwnershipHand": "Ένας άλλος παίκτης αλληλεπιδρά με αυτό το αντικείμενο", "Nitrox_DisconnectedSession": "Αποσυνδέση από τον διακομιστή", "Nitrox_DiscordAccept": "Αποδέχομαι", "Nitrox_DiscordDecline": "Αρνούμαι", + "Nitrox_DiscordInGame": "Παίζει ως {PLAYER}", + "Nitrox_DiscordInGameState": "Βουτιά στην άβυσσο", + "Nitrox_DiscordMainMenuState": "Παραμονεύει στο μενού", + "Nitrox_DiscordMultiplayerMenu": "Εάν θέλετε να συμμετάσχετε σε μια συνεδρία, πατήστε το κουμπί Multiplayer στο κύριο μενού", "Nitrox_DiscordPressToFocus": "Πατήστε για ξεκλείδωμα", "Nitrox_DiscordRequestText": "Ζητήθηκε να συμμετάσχει στο παιχνίδη σας", "Nitrox_EnterName": "Εισαγάγετε το όνομα του παίκτη σας", + "Nitrox_ErrorDesyncDetected": "[Safe Building] Αυτή η βάση είναι προς το παρόν αποσυγχρονισμένη, επομένως δεν μπορείτε να την τροποποιήσετε εκτός και αν επανασυγχρονίσετε κτίρια (στις ρυθμίσεις Nitrox)", + "Nitrox_ErrorRecentBuildUpdate": "Δεν είναι δυνατή η τροποποίηση μιας βάσης που ενημερώθηκε πρόσφατα από άλλο παίχτη.", + "Nitrox_Failure": "Προέκυψε ένα σφάλμα", + "Nitrox_FinishedResyncRequest": "Χρειάστηκαν {TIME}ms για να επανασυγχρονιστούν {COUNT} οντότητες", "Nitrox_FirewallInterfering": "Φαίνεται ότι οι ρυθμίσεις του τείχους προστασίας σας παρεμβαίνουν", "Nitrox_HideIp": "Απόκρυψη διευθύνσεων IP", + "Nitrox_HidePing": "Απόκρυψη Ping", + "Nitrox_IntroUWEPresents": "UNKNOWN WORLDS ENTERTAINMENT\n&\nΗ ΟΜΑΔΑ NITROX\n\nΠΑΡΟΥΣΙΑΖΟΥΝ", + "Nitrox_IntroWaitingPartner": "Αναμονή υπόλοιπων παιχτών\n\nΠατήστε {0} για να παραλείψετε την αναμονή", "Nitrox_InvalidUserName": "Εισαγάγετε ένα έγκυρο όνομα παίκτη.\n\nΔεν μπορεί να περιέχει κενό χώρο ή αμφίβολους χαρακτήρες\nΕπιτρεπόμενοι χαρακτήρες : A-Z a-z 0-9 _ . -\nΜήκος: [3, 25]", "Nitrox_Join": "Σύνδεση", - "Nitrox_JoinServerFailed": "Δεν είναι δυνατή η σύνδεση στον διακομιστή", - "Nitrox_JoinServerIpAddress": "IP του διακομιστή", "Nitrox_JoinServerPassword": "Κωδικός πρόσβασης:", "Nitrox_JoinServerPasswordHeader": "Απαιτείται κωδικός πρόσβασης διακομιστή", "Nitrox_JoiningSession": "Σύνδεση σε συνεδρία πολλών παικτών", + "Nitrox_Kick": "Διώξε {PLAYER}", + "Nitrox_KickQuestion": "Διώξε {PLAYER}?", "Nitrox_LaunchGame": "Έναρξη παιχνιδιού…", "Nitrox_LoadingScreenWarn": "Αναμένετε σφάλματα που θα σπάσουν το παιχνίδι", "Nitrox_LostConnection": "Χάθηκε η σύνδεση με τον διακομιστή του παιχνιδιού", "Nitrox_LostConnectionWarn": "Δεν υπάρχει σύνδεση με τον διακομιστή", "Nitrox_Multiplayer": "Multiplayer", "Nitrox_MultiplayerLoaded": "Φόρτωση προγράμματος-πελάτη για πολλούς παίκτες…", - "Nitrox_PlayerColor": "Χρώμα Παίκτη", + "Nitrox_Mute": "Σίγαση {PLAYER}", + "Nitrox_MuteQuestion": "Σίγαση {PLAYER}?", + "Nitrox_MutedPlayer": "Έγινε σίγαση του {PLAYER}", + "Nitrox_OutOfDateClient": "Η έκδοση του Nitrox σας, δεν είναι ενημερωμένη. Διακομιστής: {serverVersion}, Δικός σας: {localVersion}.", + "Nitrox_OutOfDateServer": "Ο διακομιστής εκτελεί μια παλαιότερη έκδοση του Nitrox. Ζητήστε από τον διαχειριστή να αναβαθμίσει τον διακομιστή ή να υποβαθμίσει την εγκατάσταση Nitrox. Διακομιστής: {serverVersion}, Δικός σας: {localVersion}.", + "Nitrox_PlayerDied": "Ο {PLAYER} πέθανε", + "Nitrox_PlayerDisconnected": "Ο παίκτης {PLAYER} αποσυνδέθηκε", + "Nitrox_PlayerJoined": "{PLAYER} μπήκε στο παιχνίδι.", "Nitrox_PlayerKicked": "Σας έδιωξαν από τον διακομιστή", + "Nitrox_PlayerLeft": "{ΠΑΙΚΤΗΣ} αποχώρησε από το παιχνίδι.", + "Nitrox_PlayerListTabName": "Λίστα παικτών", "Nitrox_RejectedSessionPolicy": "Η κράτηση απορρίφθηκε…", + "Nitrox_RemotePlayerObstacle": "Ένας άλλος παίκτης βρίσκεται μέσα ή πολύ κοντά στον αποδομήσιμο στόχο.", "Nitrox_RequestingSessionPolicy": "Αίτημα πληροφοριών περιόδου σύνδεσης…", + "Nitrox_ResyncBuildings": "Επανασυγχρονισμός κτιρίων βάσης", + "Nitrox_ResyncOnCooldown": "Πρέπει να περιμένετε {TIME_LEFT} δευτερόλεπτα για να στείλετε άλλο αίτημα επανασυγχρονισμού", + "Nitrox_ResyncRequested": "Εξέδωσε αίτημα επανασυγχρονισμού για βάσεις", + "Nitrox_ResyncSettings": "Επανσυγχρονισμός", + "Nitrox_SafeBuilding": "Ασφαλές κτίριο", + "Nitrox_SafeBuildingLog": "Ημερολόγιο ασφαλούς κτιρίου", "Nitrox_ServerStopped": "Ο διακομιστής σταμάτησε", + "Nitrox_ShowPing": "Εμφάνιση Ping", "Nitrox_SilenceChat": "Σίγαση συνομιλίας", "Nitrox_SilencedChatNotif": "Η συνομιλία είναι πλέον σε σίγαση", "Nitrox_StartServer": "Ξεκινήστε πρώτα τον διακομιστή σας για να συνδεθείτε στον κόσμο σας", "Nitrox_StreamerSettings": "Λειτουργία ροής (για streamers)", - "Nitrox_SubmitPassword": "Υποβολή", "Nitrox_SyncingWorld": "Συγχρονισμός κόσμου για πολλούς παίκτες…", + "Nitrox_TeleportTo": "Τηλεμεταφορά σε {PLAYER}", + "Nitrox_TeleportToMe": "Τηλεμεταφέρετε τον {PLAYER} σε εμένα", + "Nitrox_TeleportToMeQuestion": "Τηλεμεταφορά {PLAYER} σε εμένα;", + "Nitrox_TeleportToQuestion": "Τηλεμεταφορά στο {PLAYER};", + "Nitrox_ThankForPlaying": "Ευχαριστούμε για τη χρήση του Nitrox!", "Nitrox_UnableToConnect": "Δεν είναι δυνατή η επικοινωνία με τον διακομιστή στη διεύθυνση:", + "Nitrox_Unmute": "Κατάργηση σίγασης {PLAYER}", + "Nitrox_UnmuteQuestion": "Κατάργηση σίγασης {PLAYER}?", + "Nitrox_UnmutedPlayer": "Καταργήθηκε η σίγαση του {PLAYER}", "Nitrox_Waiting": "Αναμονή στην ουρά συμμετοχής…", "Nitrox_WaitingPassword": "Αναμονή για εισαγωγή κωδικού πρόσβασης διακομιστή…", "Nitrox_WaitingUserInput": "Αναμονή για εισαγωγή από τον χρήστη…", diff --git a/Nitrox.Assets.Subnautica/LanguageFiles/en.json b/Nitrox.Assets.Subnautica/LanguageFiles/en.json index 68ad021b42..a2415bd751 100644 --- a/Nitrox.Assets.Subnautica/LanguageFiles/en.json +++ b/Nitrox.Assets.Subnautica/LanguageFiles/en.json @@ -1,12 +1,20 @@ { "Nitrox_AddServer": "Add Server", - "Nitrox_AddServerAdd": "Add", - "Nitrox_AddServerHost": "Host:", - "Nitrox_AddServerName": "Name:", - "Nitrox_AddServerPort": "Port:", + "Nitrox_AddServer_AddressDescription": "Host:", + "Nitrox_AddServer_AddressPlaceholder": "Enter the IP or address of the server", + "Nitrox_AddServer_Confirm": "Create server", + "Nitrox_AddServer_InvalidInput": "You input is invalid. Please check if all text boxes are filled out.", + "Nitrox_AddServer_NameDescription": "Name:", + "Nitrox_AddServer_NamePlaceholder": "Enter a name for the server", + "Nitrox_AddServer_PortDescription": "Port:", + "Nitrox_AddServer_PortPlaceholder": "Enter the numeric port of the server", + "Nitrox_BuildingDesyncDetected": "Server detected a desync with the local client's buildings (go to Nitrox settings to request a resync)", + "Nitrox_BuildingSettings": "Base building", "Nitrox_Cancel": "Cancel", "Nitrox_CommandNotAvailable": "This command is not available in Nitrox", + "Nitrox_Confirm": "Confirm", "Nitrox_ConnectTo": "Connect to", + "Nitrox_DenyOwnershipHand": "Another player is interacting with that object", "Nitrox_DisconnectedSession": "Disconnected from server", "Nitrox_DiscordAccept": "Accept", "Nitrox_DiscordDecline": "Decline", @@ -17,40 +25,59 @@ "Nitrox_DiscordPressToFocus": "Press to unlock", "Nitrox_DiscordRequestText": "Requested to join your session", "Nitrox_EnterName": "Enter your player name", + "Nitrox_ErrorDesyncDetected": "[Safe Building] This base is currently desynced so you can't modify it unless you resync buildings (in Nitrox settings)", + "Nitrox_ErrorRecentBuildUpdate": "Cannot modify a base that was recently updated by another player", "Nitrox_Failure": "An error occured", + "Nitrox_FinishedResyncRequest": "Took {TIME}ms to resync {COUNT} entities", "Nitrox_FirewallInterfering": "Seems like your firewall settings are interfering", "Nitrox_HideIp": "Hide IP addresses", "Nitrox_HidePing": "Hide Ping", + "Nitrox_IntroUWEPresents": "UNKNOWN WORLDS ENTERTAINMENT\n&\nTHE NITROX-TEAM\n\nPRESENT", + "Nitrox_IntroWaitingPartner": "Waiting for a partner to join\n\nPress {0} to skip waiting", "Nitrox_InvalidUserName": "Please enter a valid player name.\n\nIt can not contain any space or dubious characters\nAllowed characters: A-Z a-z 0-9 _ . -\nLength: [3, 25]", "Nitrox_Join": "Join", - "Nitrox_JoinServerFailed": "Unable to join server", - "Nitrox_JoinServerIpAddress": "Server IP", + "Nitrox_JoinServer": "Joining:", "Nitrox_JoinServerPassword": "Password:", "Nitrox_JoinServerPasswordHeader": "Server password required", + "Nitrox_JoinServerPlaceholder": "Please enter the server password", "Nitrox_JoiningSession": "Joining Multiplayer Session", "Nitrox_Kick": "Kick {PLAYER}", "Nitrox_KickQuestion": "Kick {PLAYER}?", "Nitrox_LaunchGame": "Launching game…", + "Nitrox_Loading": "Loading", "Nitrox_LoadingScreenWarn": "Expect game-breaking bugs", "Nitrox_LostConnection": "Lost connection to game server", "Nitrox_LostConnectionWarn": "No longer connected to the server", + "Nitrox_MissingPermission": "You don't have permission to execute this command [{PERMISSION}]", "Nitrox_Multiplayer": "Multiplayer", "Nitrox_MultiplayerLoaded": "Multiplayer client loaded…", "Nitrox_Mute": "Mute {PLAYER}", "Nitrox_MuteQuestion": "Mute {PLAYER}?", "Nitrox_MutedPlayer": "Muted {PLAYER}", - "Nitrox_PlayerColor": "Player Color", + "Nitrox_OK": "Ok", + "Nitrox_OutOfDateClient": "Your Nitrox installation is out of date. Server: {serverVersion}, Yours: {localVersion}.", + "Nitrox_OutOfDateServer": "The server runs an older version of Nitrox. Ask the server admin to upgrade the server or downgrade your Nitrox installation. Server: {serverVersion}, Yours: {localVersion}.", + "Nitrox_PlayerDied": "{PLAYER} died", + "Nitrox_PlayerDisconnected": "{PLAYER} disconnected", + "Nitrox_PlayerJoined": "{PLAYER} joined the game.", "Nitrox_PlayerKicked": "You've been kicked from the server", + "Nitrox_PlayerLeft": "{PLAYER} left the game.", "Nitrox_PlayerListTabName": "Player List", "Nitrox_RejectedSessionPolicy": "Reservation rejected…", + "Nitrox_RemotePlayerObstacle": "Another player's either inside or too close to the deconstructable target.", "Nitrox_RequestingSessionPolicy": "Requesting session policy info…", + "Nitrox_ResyncBuildings": "Resync base buildings", + "Nitrox_ResyncOnCooldown": "You need to wait {TIME_LEFT} seconds to send another resync request", + "Nitrox_ResyncRequested": "Issued a resync request for bases", + "Nitrox_ResyncSettings": "Resynchronization", + "Nitrox_SafeBuilding": "Safe building", + "Nitrox_SafeBuildingLog": "Safe building log", "Nitrox_ServerStopped": "The server has been stopped", "Nitrox_ShowPing": "Show Ping", "Nitrox_SilenceChat": "Mute chat", "Nitrox_SilencedChatNotif": "Chat is now muted", "Nitrox_StartServer": "Start your server first to join your self-hosted world", "Nitrox_StreamerSettings": "Streamer mode", - "Nitrox_SubmitPassword": "Submit", "Nitrox_SyncingWorld": "Syncing multiplayer world…", "Nitrox_TeleportTo": "Teleport to {PLAYER}", "Nitrox_TeleportToMe": "Teleport {PLAYER} to me", @@ -64,8 +91,5 @@ "Nitrox_Waiting": "Waiting in join queue…", "Nitrox_WaitingPassword": "Waiting for server password input…", "Nitrox_WaitingUserInput": "Waiting for user input…", - "Nitrox_WorldSettling": "Awaiting World Settling…", - "Nitrox_RemotePlayerObstacle": "Another player's either inside or too close to the deconstructable target.", - "Nitrox_PlayerJoined": "{PLAYER} joined the game.", - "Nitrox_PlayerLeft": "{PLAYER} left the game." + "Nitrox_WorldSettling": "Awaiting World Settling…" } diff --git a/Nitrox.Assets.Subnautica/LanguageFiles/es-419.json b/Nitrox.Assets.Subnautica/LanguageFiles/es-419.json index ef74d9d561..d958e5d274 100644 --- a/Nitrox.Assets.Subnautica/LanguageFiles/es-419.json +++ b/Nitrox.Assets.Subnautica/LanguageFiles/es-419.json @@ -1,9 +1,5 @@ { "Nitrox_AddServer": "Añadir Servidor", - "Nitrox_AddServerAdd": "Añadir", - "Nitrox_AddServerHost": "Anfitrión:", - "Nitrox_AddServerName": "Nombre:", - "Nitrox_AddServerPort": "Puerto:", "Nitrox_Cancel": "Cancelar", "Nitrox_CommandNotAvailable": "Este comando no esta disponible en Nitrox", "Nitrox_ConnectTo": "Conectarse a", @@ -23,8 +19,6 @@ "Nitrox_HidePing": "Ocultar Latencia", "Nitrox_InvalidUserName": "Por favor ingresa un nombre de jugador válido\n\nNo puede contener espacios o carácteres extraños\nCarácteres permitidos: A-Z a-z 0-9 _ .\nLargo: [3, 25]", "Nitrox_Join": "Unirse", - "Nitrox_JoinServerFailed": "No se pudo unir al servidor", - "Nitrox_JoinServerIpAddress": "IP del Servidor", "Nitrox_JoinServerPassword": "Contraseña:", "Nitrox_JoinServerPasswordHeader": "Contraseña del Servidor requerida", "Nitrox_JoiningSession": "Uniendose a Sesión Multijugador", @@ -39,10 +33,10 @@ "Nitrox_Mute": "Silenciar a {PLAYER}", "Nitrox_MuteQuestion": "¿Silenciar a {PLAYER}?", "Nitrox_MutedPlayer": "{PLAYER} Silenciado", - "Nitrox_PlayerColor": "Color de Jugador", "Nitrox_PlayerKicked": "Has sido expulsado del servidor", "Nitrox_PlayerListTabName": "Lista de Jugadores", "Nitrox_RejectedSessionPolicy": "Reserva Rechazada…", + "Nitrox_RemotePlayerObstacle": "Otro jugador está dentro o demasiado cerca del objetivo para destruirlo.", "Nitrox_RequestingSessionPolicy": "Solicitando la información sobre la política de sesiones…", "Nitrox_ServerStopped": "El servidor se detuvo", "Nitrox_ShowPing": "Mostrar Latencia", @@ -50,7 +44,6 @@ "Nitrox_SilencedChatNotif": "El chat esta silenciado", "Nitrox_StartServer": "Primero inicia tu servidor para unirte a tu propio servidor alojado", "Nitrox_StreamerSettings": "Modo Streamer", - "Nitrox_SubmitPassword": "Enviar", "Nitrox_SyncingWorld": "Sincronizando mundo multijugador…", "Nitrox_TeleportTo": "Teleportarse a {PLAYER}", "Nitrox_TeleportToMe": "Teleportar {PLAYER} hacia mi", diff --git a/Nitrox.Assets.Subnautica/LanguageFiles/es.json b/Nitrox.Assets.Subnautica/LanguageFiles/es.json index 464116863d..483135a143 100644 --- a/Nitrox.Assets.Subnautica/LanguageFiles/es.json +++ b/Nitrox.Assets.Subnautica/LanguageFiles/es.json @@ -1,12 +1,12 @@ { "Nitrox_AddServer": "Añadir servidor", - "Nitrox_AddServerAdd": "Añadir", - "Nitrox_AddServerHost": "Dirección:", - "Nitrox_AddServerName": "Nombre:", - "Nitrox_AddServerPort": "Port:", + "Nitrox_BuildingDesyncDetected": "El servidor detectó una desincronización con un edificio del cliente local (Ve a las opciones de Nitrox para solicitar una resincronización)", + "Nitrox_BuildingSettings": "Construcción de bases", "Nitrox_Cancel": "Cancelar", "Nitrox_CommandNotAvailable": "Este comando no está disponible con Nitrox", + "Nitrox_Confirm": "Confirmar", "Nitrox_ConnectTo": "Conectarse a", + "Nitrox_DenyOwnershipHand": "Otro jugador esta interactiando con ese objeto", "Nitrox_DisconnectedSession": "Desconectado del servidor", "Nitrox_DiscordAccept": "Aceptar", "Nitrox_DiscordDecline": "Cancelar", @@ -17,16 +17,21 @@ "Nitrox_DiscordPressToFocus": "Pulse para desbloquear", "Nitrox_DiscordRequestText": "Solicita unirse a la sesión", "Nitrox_EnterName": "Nombre del jugador", + "Nitrox_ErrorDesyncDetected": "[Construcción segura] Esta base esta desincronizada y no podrá ser modificada hasta realizar una resincronización (En las opciones de Nitrox)", + "Nitrox_ErrorRecentBuildUpdate": "No puede modificar una base que fue recientemente actualizada por otro jugador", "Nitrox_Failure": "Se ha producido un error", + "Nitrox_FinishedResyncRequest": "Tomó {TIME} ms para sincronizar {COUNT} entidades", "Nitrox_FirewallInterfering": "Parece que la configuración de tu cortafuegos está interfiriendo", "Nitrox_HideIp": "Ocultar IPs", "Nitrox_HidePing": "Ocultar señal", + "Nitrox_IntroUWEPresents": "UNKNOWN WORLDS ENTERTAINMENT\n&\nEL EQUIPO DE NITROX\n\nPRESENTAN", + "Nitrox_IntroWaitingPartner": "Esperando a un compañero para unirse\n\nPresiona {0} para saltar la espera", "Nitrox_InvalidUserName": "Por favor, introduzca un nombre de jugador válido !\n\nNo debe contener ningún espacio o caracteres dudosos\nCaracteres permitidos : A-Z a-z 0-9 _ . -\nLargo : [3, 25]", "Nitrox_Join": "Entrar", - "Nitrox_JoinServerFailed": "Error al conectar con el servidor", - "Nitrox_JoinServerIpAddress": "Dirección del servidor", + "Nitrox_JoinServer": "Entrando:", "Nitrox_JoinServerPassword": "Contraseña:", "Nitrox_JoinServerPasswordHeader": "Contraseña requerido", + "Nitrox_JoinServerPlaceholder": "Por favor introduzca la contraseña del servidor", "Nitrox_JoiningSession": "Conectando con el mundo multijugador", "Nitrox_Kick": "Expulsar a {PLAYER}", "Nitrox_KickQuestion": "¿Expulsar a {PLAYER}?", @@ -34,23 +39,36 @@ "Nitrox_LoadingScreenWarn": "Espere alguna inestabilidad", "Nitrox_LostConnection": "Conexión perdida al servidor", "Nitrox_LostConnectionWarn": "Ya no está conectado al servidor", + "Nitrox_MissingPermission": "No tienes permiso para ejecutar este comando [{PERMISO}]", "Nitrox_Multiplayer": "Multijugador", "Nitrox_MultiplayerLoaded": "Cliente multijugador cargado…", "Nitrox_Mute": "Silenciar a {PLAYER}", "Nitrox_MuteQuestion": "¿Silenciar a {PLAYER}?", "Nitrox_MutedPlayer": "{PLAYER} Silenciado", - "Nitrox_PlayerColor": "Color", + "Nitrox_OK": "Ok", + "Nitrox_OutOfDateClient": "Tu versión de Nitrox esta desactualizada. Servidor:{serverVersion}, La tuya:{localVersion}.", + "Nitrox_OutOfDateServer": "El servidor utiliza una versión antigua de Nitrox. Pídele al administrador del servidor que actualice el servidor o utiliza una versión de Nitrox más antigua. Servidor: {serverVersion}, Tu versión: {localVersion}.", + "Nitrox_PlayerDied": "{PLAYER} Ha muerto", + "Nitrox_PlayerDisconnected": "{PLAYER} Se ha desconectado", + "Nitrox_PlayerJoined": "{PLAYER} se ha unido.", "Nitrox_PlayerKicked": "Expulsado del servidor", + "Nitrox_PlayerLeft": "{PLAYER} se ha ido.", "Nitrox_PlayerListTabName": "Lista de Jugadores", "Nitrox_RejectedSessionPolicy": "Reservación rechazada…", + "Nitrox_RemotePlayerObstacle": "Otro jugador está dentro o demasiado cerca del objetivo para destruirlo.", "Nitrox_RequestingSessionPolicy": "Conectando con el servidor…", + "Nitrox_ResyncBuildings": "Resincronizar construcciones de base", + "Nitrox_ResyncOnCooldown": "Debes esperar {TIME_LEFT} segundos para solicitar otra sincronización", + "Nitrox_ResyncRequested": "Solicitada una sincronización para bases", + "Nitrox_ResyncSettings": "Re-sincronización", + "Nitrox_SafeBuilding": "Construcción segura", + "Nitrox_SafeBuildingLog": "Registro de construcción segura", "Nitrox_ServerStopped": "El servidor se ha parado", "Nitrox_ShowPing": "Mostrar señal", "Nitrox_SilenceChat": "Silenciar el chat", "Nitrox_SilencedChatNotif": "Se silencia el chat", "Nitrox_StartServer": "Inicie su servidor para alcanzar a su mundo", "Nitrox_StreamerSettings": "Modo streamer", - "Nitrox_SubmitPassword": "Enviar contraseña", "Nitrox_SyncingWorld": "Sincronización del mundo multijugador…", "Nitrox_TeleportTo": "Teleportar hacia {PLAYER}", "Nitrox_TeleportToMe": "Teleportar {PLAYER} hacia mi", diff --git a/Nitrox.Assets.Subnautica/LanguageFiles/et.json b/Nitrox.Assets.Subnautica/LanguageFiles/et.json index afcd2064a4..6e0df9725f 100644 --- a/Nitrox.Assets.Subnautica/LanguageFiles/et.json +++ b/Nitrox.Assets.Subnautica/LanguageFiles/et.json @@ -1,24 +1,21 @@ { "Nitrox_AddServer": "Lisa Server", - "Nitrox_AddServerAdd": "Lisa", - "Nitrox_AddServerHost": "Tee Server:", - "Nitrox_AddServerName": "Nimi:", - "Nitrox_AddServerPort": "Port:", "Nitrox_Cancel": "Lõpeta", "Nitrox_CommandNotAvailable": "Sellist käsku pole olemas Nitroxis", "Nitrox_ConnectTo": "Ühenda", "Nitrox_DisconnectedSession": "Serverist lahkunud", "Nitrox_DiscordAccept": "Võta vastu", "Nitrox_DiscordDecline": "Ära võta vastu", + "Nitrox_DiscordInGameState": "Sukeldud sügavikku", + "Nitrox_DiscordMultiplayerMenu": "Vajuta menüüs Multiplayer nupule, kui sa tahad ühineda sessiooniga", "Nitrox_DiscordPressToFocus": "Vajuta et avada", "Nitrox_DiscordRequestText": "Tahtis sinu mängu tulla", "Nitrox_EnterName": "Sisesta oma mängija nimi", "Nitrox_FirewallInterfering": "Tundub et teie tulemüüri (firewall) sätted sekkuvad", "Nitrox_HideIp": "Peida IP aadressid", + "Nitrox_HidePing": "Peida Ping", "Nitrox_InvalidUserName": "Palun sisesta sobiv mängija nimi.\n\nSelles ei tohi olla tühikuid või kahtlaseid tähti\nLubatud tähed: A-Z a-z 0-9 _ . -\nPikkus: [3, 25]", "Nitrox_Join": "Liitu", - "Nitrox_JoinServerFailed": "Ei saa liituda serveriga", - "Nitrox_JoinServerIpAddress": "Serveri IP", "Nitrox_JoinServerPassword": "Parool:", "Nitrox_JoinServerPasswordHeader": "Serveri parool vajatud", "Nitrox_JoiningSession": "Serveriga liitumine", @@ -28,7 +25,6 @@ "Nitrox_LostConnectionWarn": "Pole enam serveriga ühendatud", "Nitrox_Multiplayer": "Serverid", "Nitrox_MultiplayerLoaded": "Server laetud…", - "Nitrox_PlayerColor": "Mängija värv", "Nitrox_PlayerKicked": "Sind visati serverist välja", "Nitrox_RejectedSessionPolicy": "Reserveerimine keelatud…", "Nitrox_RequestingSessionPolicy": "Ootamine…", @@ -37,7 +33,6 @@ "Nitrox_SilencedChatNotif": "Vestlus on nüüd vaigistatud", "Nitrox_StartServer": "Alusta oma server enne, et liituda oma enda maailmaga", "Nitrox_StreamerSettings": "Streameri mood", - "Nitrox_SubmitPassword": "Esita", "Nitrox_SyncingWorld": "serveri maailmaga sünkroonimine…", "Nitrox_UnableToConnect": "Ei saa ühendada serveriga:", "Nitrox_Waiting": "Ootamine liitumis järjekorras…", diff --git a/Nitrox.Assets.Subnautica/LanguageFiles/fi.json b/Nitrox.Assets.Subnautica/LanguageFiles/fi.json index 8c2b710418..cc024192ed 100644 --- a/Nitrox.Assets.Subnautica/LanguageFiles/fi.json +++ b/Nitrox.Assets.Subnautica/LanguageFiles/fi.json @@ -1,47 +1,84 @@ { "Nitrox_AddServer": "Lisää palvelin", - "Nitrox_AddServerAdd": "Lisää", - "Nitrox_AddServerHost": "Isäntä:", - "Nitrox_AddServerName": "Nimi:", - "Nitrox_AddServerPort": "Portti:", + "Nitrox_BuildingDesyncDetected": "Palvelin havaitsi epäsynkronoinnin paikallisen asiakkaan rakennuksissa (pyydä uudelleensynkronointia Nitroxin asetuksissa)", + "Nitrox_BuildingSettings": "Tukikohtarakennus", "Nitrox_Cancel": "Hylkää", - "Nitrox_CommandNotAvailable": "Tämä komento ei ola saatavilla Nitroxissa.", + "Nitrox_CommandNotAvailable": "Tämä komento ei ole saatavilla Nitrox:issa", + "Nitrox_Confirm": "Vahvista", "Nitrox_ConnectTo": "Yhdistä", + "Nitrox_DenyOwnershipHand": "Toinen pelaaja kayttää tuota tällä hetkellä", "Nitrox_DisconnectedSession": "Yhteys palvelimeen on katkaistu", "Nitrox_DiscordAccept": "Hyväksy", + "Nitrox_DiscordDecline": "Kieltäydy", + "Nitrox_DiscordInGame": "Pelaa nimellä {PLAYER}", + "Nitrox_DiscordInGameState": "Sukeltamassa syövereihin", + "Nitrox_DiscordMainMenuState": "Valikossa väijymässä", + "Nitrox_DiscordMultiplayerMenu": "Valitse Moninpeli päävalikossa, jos haluat liittyä istuntoon", + "Nitrox_DiscordPressToFocus": "Paina avataksesi lukituksen", "Nitrox_DiscordRequestText": "Pyytää liittyä istuntoosi", - "Nitrox_EnterName": "Pelaaja nimi", - "Nitrox_FirewallInterfering": "Näyttää siltä että palomuuri asetuksesi häiritsevät palvelinta", + "Nitrox_EnterName": "Pelaajanimesi", + "Nitrox_ErrorDesyncDetected": "[Turvallinen rakennus] Tämä tukikohta on tällä hetkellä epäsynkronoitu, joten et pysty muokkaamaan sitä ellet uudelleensynkronoi rakennuksia (Nitroxin asetuksissa)", + "Nitrox_ErrorRecentBuildUpdate": "Ei pystytä muokkaamaan tukikohtaa, joka oli äskettäin päivitetty toisen pelaajan toimesta", + "Nitrox_Failure": "Virhe tapahtui", + "Nitrox_FinishedResyncRequest": "Kesti {TIME}ms, että saatiin uudelleensynkronoitua {COUNT} eliötä", + "Nitrox_FirewallInterfering": "Näyttää siltä, että palomuuriasetuksesi aiheuttavat ongelmia", "Nitrox_HideIp": "Piilota IP-osoitteet", - "Nitrox_InvalidUserName": "Syötä kelvollinen pelaaja nimi !\n\n Pelaaja nimi ei saa sisältää välilyöntejä tai merkkejä \n Sallitut merkit : A-Z a-z 0-9 _ . -\nLength : [3, 25]", + "Nitrox_HidePing": "Piilota Ping", + "Nitrox_IntroUWEPresents": "UNKNOWN WORLDS ENTERTAINMENT\n&\nNITROX-TIIMI\n\nESITTÄÄ", + "Nitrox_IntroWaitingPartner": "Odotetaan toisen pelaajan liittymistä\n\nPaina {0} ohittaaksesi", + "Nitrox_InvalidUserName": "Syötä kelvollinen pelaajanimi!\n\nPelaajanimi ei saa sisältää välilyöntejä tai merkkejä\nSallitut merkit : A-Z a-z 0-9 _ . -\nPituus : [3, 25]", "Nitrox_Join": "Liity", - "Nitrox_JoinServerFailed": "Palvelimelle ei pystynyt liittymään", - "Nitrox_JoinServerIpAddress": "Palvelimen IP osoite", + "Nitrox_JoinServer": "Liitytään:", "Nitrox_JoinServerPassword": "Salasana:", "Nitrox_JoinServerPasswordHeader": "Palvelin vaatii salasanan", - "Nitrox_JoiningSession": "Liitytään moninpeli istuntoon", + "Nitrox_JoinServerPlaceholder": "Syötä palvelimen salasana", + "Nitrox_JoiningSession": "Liitytään moninpeli-istuntoon", + "Nitrox_Kick": "Potkaise ulos {PLAYER}", + "Nitrox_KickQuestion": "Potkaise ulos {PLAYER}?", "Nitrox_LaunchGame": "Käynnistetään peliä…", - "Nitrox_LoadingScreenWarn": "Odota peliä rikkovia bugeja ja pelin kaatumista", - "Nitrox_LostConnection": "Yhteys palvelimeen katkaistu", + "Nitrox_LoadingScreenWarn": "Pelin rikkovat bugit ja pelin kaatuminen on mahdollista", + "Nitrox_LostConnection": "Yhteys pelipalvelimeen katkesi", "Nitrox_LostConnectionWarn": "Et ole enää yhdistettynä palvelimeen", + "Nitrox_MissingPermission": "Sinulla ei ole käyttöoikeuksia suorittaa tätä komentoa [{PERMISSION}]", "Nitrox_Multiplayer": "Moninpeli", "Nitrox_MultiplayerLoaded": "Moninpeli ladattu…", "Nitrox_Mute": "Mykistä {PLAYER}", "Nitrox_MuteQuestion": "Mykistä {PLAYER}?", "Nitrox_MutedPlayer": "{PLAYER} on mykistetty", - "Nitrox_PlayerColor": "Pelaaja väri", - "Nitrox_PlayerKicked": "Sinut on potkittu peli palvelimelta", + "Nitrox_OK": "Ok", + "Nitrox_OutOfDateClient": "Nitrox-asennuksesi on vanhentunut. Palvelin: {serverVersion}, Asennuksesi: {serverVersion}.", + "Nitrox_OutOfDateServer": "Palvelimella on vanhempi versio Nitroxista. Pyydä palvelimen omistajaa päivittämään palvelin tai asenna vanhempi versio Nitroxista. Palvelin: {serverVersion}, Asennuksesi: {localVersion}.", + "Nitrox_PlayerDied": "{PLAYER} kuoli", + "Nitrox_PlayerDisconnected": "Pelaajan {PLAYER} yhteys katkesi", + "Nitrox_PlayerJoined": "{PLAYER} liittyi peliin.", + "Nitrox_PlayerKicked": "Sinut on potkittu palvelimelta", + "Nitrox_PlayerLeft": "{PLAYER} poistui pelistä.", "Nitrox_PlayerListTabName": "Pelaajalista", "Nitrox_RejectedSessionPolicy": "Varaus hylätty…", + "Nitrox_RemotePlayerObstacle": "Toinen pelaaja on joko purettavan kohteen sisällä tai liian lähellä sitä.", "Nitrox_RequestingSessionPolicy": "Istuntokäytäntötietojen pyytäminen…", + "Nitrox_ResyncBuildings": "Uudelleensynkronoi tukikohdan rakennukset", + "Nitrox_ResyncOnCooldown": "Sinun täytyy odottaa {TIME_LEFT} sekuntia, että voit lähettää toisen uudelleensynkronointipyynnön", + "Nitrox_ResyncRequested": "Tukikohdille on lähetetty uudelleensynkronointipyyntö", + "Nitrox_ResyncSettings": "Uudelleensynkronointi", + "Nitrox_SafeBuilding": "Turvallinen rakennus", + "Nitrox_SafeBuildingLog": "Turvallisen rakennuksen loki", "Nitrox_ServerStopped": "Palvelin on pysäytetty", + "Nitrox_ShowPing": "Näytä Ping", "Nitrox_SilenceChat": "Mykistä chat", "Nitrox_SilencedChatNotif": "Keskustelu on nyt mykistetty", - "Nitrox_StartServer": "Käynnistä palvelin ensiksi niin voit liittyä itse hostaamaan maailmaasi", - "Nitrox_StreamerSettings": "Streamer-tila", - "Nitrox_SubmitPassword": "Syötä salasana", + "Nitrox_StartServer": "Käynnistä palvelin ensin, niin voit liittyä itse isännöityyn maailmaasi", + "Nitrox_StreamerSettings": "Streamaaja-tila", "Nitrox_SyncingWorld": "Synkataan moninpeli maailmaa…", - "Nitrox_UnableToConnect": "Etäpalvelimeen ei voitu ottaa yhteyttä osoitteessa:", + "Nitrox_TeleportTo": "Teleporttaa {PLAYER} luokse", + "Nitrox_TeleportToMe": "Teleporttaa {PLAYER} luokseni", + "Nitrox_TeleportToMeQuestion": "Teleporttaa {PLAYER} luokseni?", + "Nitrox_TeleportToQuestion": "Teleporttaa {PLAYER} luokse?", + "Nitrox_ThankForPlaying": "Kiitos, kun käytit Nitroxia!", + "Nitrox_UnableToConnect": "Etäpalvelimeen ei saatu yhteyttä osoitteessa:", + "Nitrox_Unmute": "Poista {PLAYER} mykistys", + "Nitrox_UnmuteQuestion": "Poista {PLAYER} mykistys?", + "Nitrox_UnmutedPlayer": "Poistettu {PLAYER} mykistys", "Nitrox_Waiting": "Odotetaan liittymisjonossa…", "Nitrox_WaitingPassword": "Odotetaan palvelimen salasanan syöttöä…", "Nitrox_WaitingUserInput": "Odotetaan käyttäjän syöttöä…", diff --git a/Nitrox.Assets.Subnautica/LanguageFiles/fr.json b/Nitrox.Assets.Subnautica/LanguageFiles/fr.json index c48b278c5d..51e82b6157 100644 --- a/Nitrox.Assets.Subnautica/LanguageFiles/fr.json +++ b/Nitrox.Assets.Subnautica/LanguageFiles/fr.json @@ -1,67 +1,94 @@ { "Nitrox_AddServer": "Ajouter un serveur", - "Nitrox_AddServerAdd": "Ajouter", - "Nitrox_AddServerHost": "Hôte :", - "Nitrox_AddServerName": "Nom :", - "Nitrox_AddServerPort": "Port :", + "Nitrox_AddServer_AddressDescription": "Hôte :", + "Nitrox_AddServer_AddressPlaceholder": "Saisir l'IP ou l'adresse du serveur", + "Nitrox_AddServer_Confirm": "Créer", + "Nitrox_AddServer_InvalidInput": "Merci de remplir tous les champs.", + "Nitrox_AddServer_NameDescription": "Nom :", + "Nitrox_AddServer_NamePlaceholder": "Saisir un nom de serveur", + "Nitrox_AddServer_PortDescription": "Port :", + "Nitrox_AddServer_PortPlaceholder": "Saisir le port du serveur", + "Nitrox_BuildingDesyncDetected": "Le serveur a détecté une désynchronisation des constructions (voir dans les paramètres de Nitrox pour demander une resynchronisation)", + "Nitrox_BuildingSettings": "Constructions", "Nitrox_Cancel": "Annuler", "Nitrox_CommandNotAvailable": "Cette commande n'est pas disponible avec Nitrox", + "Nitrox_Confirm": "Confirmer", "Nitrox_ConnectTo": "Connexion à", + "Nitrox_DenyOwnershipHand": "Un autre joueur interagit avec cet objet", "Nitrox_DisconnectedSession": "Déconnecté du serveur", "Nitrox_DiscordAccept": "Accepter", "Nitrox_DiscordDecline": "Refuser", - "Nitrox_DiscordInGame": "Joue en tant que {Player}", + "Nitrox_DiscordInGame": "Joue en tant que {PLAYER}", "Nitrox_DiscordInGameState": "Entrain de plonger", "Nitrox_DiscordMainMenuState": "Dans le menu", - "Nitrox_DiscordMultiplayerMenu": "Merci d'appuyer sur le bouton Multijoueur du menu principal pour rejoindre une session", + "Nitrox_DiscordMultiplayerMenu": "Appuyez sur le bouton Multijoueur du menu principal pour rejoindre une session", "Nitrox_DiscordPressToFocus": "Maintenir pour déverrouiller", - "Nitrox_DiscordRequestText": "A demandé pour rejoindre votre session", + "Nitrox_DiscordRequestText": "A demandé à rejoindre votre session", "Nitrox_EnterName": "Nom du joueur", + "Nitrox_ErrorDesyncDetected": "[Safe Building] Impossible de modifier cette base tant que celle-ci est actuellement désynchronisée (voir dans les paramètres de Nitrox pour resynchroniser)", + "Nitrox_ErrorRecentBuildUpdate": "Impossible de modifier une base qui a récemment été modifiée par un autre joueur", "Nitrox_Failure": "Une erreur est survenue", + "Nitrox_FinishedResyncRequest": "Resynchronisation de {COUNT} entité(s) effectuée en {TIME}ms", "Nitrox_FirewallInterfering": "Les paramètres de votre pare-feu empêchent la connexion", "Nitrox_HideIp": "Cacher les adresses IP", "Nitrox_HidePing": "Cacher le signal", + "Nitrox_IntroUWEPresents": "UNKNOWN WORLDS ENTERTAINMENT\n&\nL'ÉQUIPE NITROX\n\nVOUS PRÉSENTE", + "Nitrox_IntroWaitingPartner": "En attente d'un partenaire\n\nAppuyez sur {0} pour passer", "Nitrox_InvalidUserName": "Veuillez entrer un nom de joueur valide.\n\nIl ne peut pas contenir d'espace ou de caractères spéciaux.\nCaractères autorisés : A-Z a-z 0-9 _ . -\nLongueur : [3, 25]", "Nitrox_Join": "Rejoindre", - "Nitrox_JoinServerFailed": "Impossible de se connecter au serveur", - "Nitrox_JoinServerIpAddress": "IP du serveur", + "Nitrox_JoinServer": "En train de joindre :", "Nitrox_JoinServerPassword": "Mot de passe :", "Nitrox_JoinServerPasswordHeader": "Mot de passe requis", + "Nitrox_JoinServerPlaceholder": "Entrer le mot de passe du serveur s'il vous plaît", "Nitrox_JoiningSession": "Connexion au monde multijoueur", "Nitrox_Kick": "Exclure {PLAYER}", "Nitrox_KickQuestion": "Exclure {PLAYER} ?", "Nitrox_LaunchGame": "Lancement du jeu…", - "Nitrox_LoadingScreenWarn": "Attendez vous à quelques instabilités", + "Nitrox_Loading": "Chargement", + "Nitrox_LoadingScreenWarn": "Attendez vous à quelques bugs", "Nitrox_LostConnection": "Connexion au serveur perdue", "Nitrox_LostConnectionWarn": "Vous n'êtes plus connecté au serveur", + "Nitrox_MissingPermission": "Vous n'avez pas la permission d'exécuter cette commande [{PERMISSION}]", "Nitrox_Multiplayer": "Multijoueur", "Nitrox_MultiplayerLoaded": "Chargement du client multijoueur…", "Nitrox_Mute": "Rendre muet {PLAYER}", "Nitrox_MuteQuestion": "Rendre muet {PLAYER} ?", - "Nitrox_MutedPlayer": "{PLAYER} est maintenant muet", - "Nitrox_PlayerColor": "Couleur", + "Nitrox_MutedPlayer": "{PLAYER} est maintenant en sourdine", + "Nitrox_OK": "Accepter", + "Nitrox_OutOfDateClient": "Votre version de Nitrox est trop ancienne. Serveur : {serverVersion}, Vous : {localVersion}.", + "Nitrox_OutOfDateServer": "Le serveur fonctionne sur une ancienne version de Nitrox. Vous pouvez contacter l'administrateur du serveur ou utiliser une version plus ancienne. Serveur : {serverVersion}, Vous : {localVersion}.", + "Nitrox_PlayerDied": "{PLAYER} est mort", + "Nitrox_PlayerDisconnected": "{PLAYER} s'est déconnecté", + "Nitrox_PlayerJoined": "{PLAYER} a rejoint la partie.", "Nitrox_PlayerKicked": "Vous avez été exclu du serveur", + "Nitrox_PlayerLeft": "{PLAYER} a quitté la partie.", "Nitrox_PlayerListTabName": "Liste des joueurs", "Nitrox_RejectedSessionPolicy": "Réservation rejetée…", + "Nitrox_RemotePlayerObstacle": "Déconstruction impossible. Un autre joueur est à l'intérieur, ou trop proche.", "Nitrox_RequestingSessionPolicy": "En attente des informations du serveur…", + "Nitrox_ResyncBuildings": "Resynchroniser les constructions", + "Nitrox_ResyncOnCooldown": "Vous devez attendre {TIME_LEFT} secondes pour renvoyer une demande de resynchronisation", + "Nitrox_ResyncRequested": "Demande de resynchronisation envoyée", + "Nitrox_ResyncSettings": "Resynchronisation", + "Nitrox_SafeBuilding": "Mode de construction sans erreur", + "Nitrox_SafeBuildingLog": "Afficher les messages du mode de construction sans erreur", "Nitrox_ServerStopped": "Le serveur a été arrêté", "Nitrox_ShowPing": "Montrer le signal", - "Nitrox_SilenceChat": "Cacher la discussion", - "Nitrox_SilencedChatNotif": "La discussion est maintenant silencieuse", - "Nitrox_StartServer": "Veuillez démarrer votre serveur pour rejoindre votre monde", + "Nitrox_SilenceChat": "Cacher la fenêtre de discussion", + "Nitrox_SilencedChatNotif": "La fenêtre de discussion est maintenant cachée", + "Nitrox_StartServer": "Démarrez d'abord votre serveur pour rejoindre votre monde", "Nitrox_StreamerSettings": "Mode streamer", - "Nitrox_SubmitPassword": "Confirmer", "Nitrox_SyncingWorld": "Synchronisation du monde multijoueur…", - "Nitrox_TeleportTo": "Se téléporter à {PLAYER}", + "Nitrox_TeleportTo": "Se téléporter vers {PLAYER}", "Nitrox_TeleportToMe": "Téléporter {PLAYER} ici", - "Nitrox_TeleportToMeQuestion": "Téléporter {PLAYER} vers moi ?", + "Nitrox_TeleportToMeQuestion": "Téléporter {PLAYER} ici ?", "Nitrox_TeleportToQuestion": "Se téléporter vers {PLAYER} ?", "Nitrox_ThankForPlaying": "Merci d'avoir utilisé Nitrox !", "Nitrox_UnableToConnect": "Impossible de se connecter au serveur :", "Nitrox_Unmute": "Entendre à nouveau {PLAYER}", "Nitrox_UnmuteQuestion": "Entendre à nouveau {PLAYER} ?", - "Nitrox_UnmutedPlayer": "{PLAYER} n'est plus muet", - "Nitrox_Waiting": "En attente dans la file de connexion…", + "Nitrox_UnmutedPlayer": "{PLAYER} n'est plus en sourdine", + "Nitrox_Waiting": "Dans la file d'attente de connexion…", "Nitrox_WaitingPassword": "En attente du mot de passe…", "Nitrox_WaitingUserInput": "En attente des informations du joueur…", "Nitrox_WorldSettling": "Chargement du monde…" diff --git a/Nitrox.Assets.Subnautica/LanguageFiles/ga.json b/Nitrox.Assets.Subnautica/LanguageFiles/ga.json index 0967ef424b..83b09b5ef0 100644 --- a/Nitrox.Assets.Subnautica/LanguageFiles/ga.json +++ b/Nitrox.Assets.Subnautica/LanguageFiles/ga.json @@ -1 +1,16 @@ -{} +{ + "Nitrox_AddServer": "Cur friothálaí leis", + "Nitrox_CommandNotAvailable": "Níl an t- ordú seo ar fáil i Nitrox", + "Nitrox_ConnectTo": "Ceangail leis", + "Nitrox_DisconnectedSession": "Dícheanglaithe ón bhfreastalaí", + "Nitrox_DiscordAccept": "Glacadh le", + "Nitrox_DiscordDecline": "Meath", + "Nitrox_DiscordInGame": "Ag imirt mar {IMREOIR}", + "Nitrox_DiscordInGameState": "Ag tumadh isteach san duibheagán", + "Nitrox_DiscordMainMenuState": "Lurking sa roghchlár", + "Nitrox_DiscordMultiplayerMenu": "Brúigh ar an gcnaipe Ilimreora sa Phríomh-Roghchlár más mian leat páirt a ghlacadh i seisiún", + "Nitrox_DiscordPressToFocus": "Brúigh chun dhíghlasáil", + "Nitrox_DiscordRequestText": "Iarrtar ort páirt a ghlacadh i do sheisiún", + "Nitrox_EnterName": "Iontráil ainm do imreora", + "Nitrox_Failure": "Tharla earráid" +} diff --git a/Nitrox.Assets.Subnautica/LanguageFiles/hr.json b/Nitrox.Assets.Subnautica/LanguageFiles/hr.json index 2638a054bd..c7a3e2def7 100644 --- a/Nitrox.Assets.Subnautica/LanguageFiles/hr.json +++ b/Nitrox.Assets.Subnautica/LanguageFiles/hr.json @@ -1,25 +1,26 @@ { - "Nitrox_AddServer": "Dodaj poslužitelj", - "Nitrox_AddServerAdd": "Dodaj", - "Nitrox_AddServerHost": "Računalo:", - "Nitrox_AddServerName": "Naziv:", - "Nitrox_AddServerPort": "Priključak:", + "Nitrox_AddServer": "Dodaj poslužitelja", + "Nitrox_BuildingDesyncDetected": "Poslužitelj je otkrio nesinkronizaciju s lokalnim korisničkim građevinama(idi na Nitrox postavke kako bi zatražio/a ponovnu sinkronizaciju)", + "Nitrox_BuildingSettings": "Izgradnja baze", "Nitrox_Cancel": "Odustani", "Nitrox_CommandNotAvailable": "Ova naredba nije dostupna u Nitroxu", "Nitrox_ConnectTo": "Poveži se na", "Nitrox_DisconnectedSession": "Veza s poslužiteljem prekinuta", "Nitrox_DiscordAccept": "Prihvati", "Nitrox_DiscordDecline": "Odbij", + "Nitrox_DiscordInGame": "Igrate kao {PLAYER}", + "Nitrox_DiscordInGameState": "Roni u oceanu", + "Nitrox_DiscordMainMenuState": "Skriva se u izborniku", + "Nitrox_DiscordMultiplayerMenu": "Molim te pritisni Multiplayer dugme u izborniku ako želiš igrati", "Nitrox_DiscordPressToFocus": "Pritisni za otključavanje", "Nitrox_DiscordRequestText": "Zatraženo je pridruživanje tvojoj sesiji", "Nitrox_EnterName": "Upiši svoje ime igrača", + "Nitrox_Failure": "Dogodila se greška", "Nitrox_FirewallInterfering": "Čini se da postavke tvog vatrozida ometaju", "Nitrox_HideIp": "Sakrij IP adrese", "Nitrox_HidePing": "Sakrij ping", - "Nitrox_InvalidUserName": "Upiši valjano ime igrača!\n\nNe smije sadržavati razmak ili sumnjive znakove\nDozvoljeni znakovi : A-Z a-z 0-9 _ . -\nDužina : [3, 25]", + "Nitrox_InvalidUserName": "Upiši valjano ime igrača!\n\nNe smije sadržavati razmaknice ili sumnjive znakove\nDozvoljeni znakovi : A-Z a-z 0-9 _ . -\nDužina : [3, 25]", "Nitrox_Join": "Pridruži se", - "Nitrox_JoinServerFailed": "Nije moguće pridružiti se poslužitelju", - "Nitrox_JoinServerIpAddress": "IP poslužitelja", "Nitrox_JoinServerPassword": "Lozinka:", "Nitrox_JoinServerPasswordHeader": "Potrebna je lozinka za poslužitelj", "Nitrox_JoiningSession": "Pridruživanje multiplayer sesiji", @@ -27,17 +28,23 @@ "Nitrox_KickQuestion": "Izbaciti igrača {PLAYER}?", "Nitrox_LaunchGame": "Pokretanje igre …", "Nitrox_LoadingScreenWarn": "Očekuj greške koje prekidaju igru", - "Nitrox_LostConnection": "Veza s poslužiteljem igara je izgubljena", + "Nitrox_LostConnection": "Veza s poslužiteljem igre je izgubljena", "Nitrox_LostConnectionWarn": "Veza s poslužiteljem više ne postoji", "Nitrox_Multiplayer": "Multiplayer", "Nitrox_MultiplayerLoaded": "Multiplayer klijent učitan …", "Nitrox_Mute": "Isključi zvuk igrača {PLAYER}", "Nitrox_MuteQuestion": "Isključiti zvuk igrača {PLAYER}?", "Nitrox_MutedPlayer": "Isključen zvuk igrača {PLAYER}", - "Nitrox_PlayerColor": "Boja igrača", + "Nitrox_OutOfDateClient": "Tvoja Nitrox instalacija je zastarjela. Poslužitelj: {serverVersion}, Tvoja: {localVersion}.", + "Nitrox_OutOfDateServer": "Poslužitelj pokreće stariju verziju Nitroxa. Zamoli administratora poslužitelja da nadogradi poslužitelj ili da vrati stariju verziju tvoje Nitrox instalacije. Poslužitelj: {serverVersion}, Tvoja: {localVersion}.", + "Nitrox_PlayerDied": "{PLAYER} je umro", + "Nitrox_PlayerDisconnected": "{PLAYER} se odspojio", + "Nitrox_PlayerJoined": "{PLAYER} se pridružio/la igri.", "Nitrox_PlayerKicked": "Izbačen/a si s poslužitelja", + "Nitrox_PlayerLeft": "{PLAYER} je napustio/la igru.", "Nitrox_PlayerListTabName": "Popis igrača", "Nitrox_RejectedSessionPolicy": "Rezervacija odbijena …", + "Nitrox_RemotePlayerObstacle": "Drugi igrač je u ili pre blizu građevine koja se ne može uništiti.", "Nitrox_RequestingSessionPolicy": "Zahtjevanje informacija o pravilima sesije …", "Nitrox_ServerStopped": "Poslužitelj je prekinuo rad", "Nitrox_ShowPing": "Prikaži ping", @@ -45,12 +52,12 @@ "Nitrox_SilencedChatNotif": "Zvuk razgovora je isključen", "Nitrox_StartServer": "Najprije pokreni svoj poslužitelj za pridruživanje vlastitom svijetu koji održavaš", "Nitrox_StreamerSettings": "Modus prijenosa", - "Nitrox_SubmitPassword": "Pošalji", "Nitrox_SyncingWorld": "Sinkronizacija multiplayer svijeta …", "Nitrox_TeleportTo": "Teleportiraj igraču {PLAYER}", "Nitrox_TeleportToMe": "Teleportiraj igrača {PLAYER} k meni", "Nitrox_TeleportToMeQuestion": "Teleportirati igrača {PLAYER} k meni?", "Nitrox_TeleportToQuestion": "Teleportirati igraču {PLAYER}?", + "Nitrox_ThankForPlaying": "Hvala na korištenju Nitrox!", "Nitrox_UnableToConnect": "Nije moguće kontaktirati udaljeni poslužitelj na:", "Nitrox_Unmute": "Isključi zvuk igrača {PLAYER}", "Nitrox_UnmuteQuestion": "Isključiti zvuk igrača {PLAYER}?", diff --git a/Nitrox.Assets.Subnautica/LanguageFiles/hu.json b/Nitrox.Assets.Subnautica/LanguageFiles/hu.json index f462a67c0a..4a689220e4 100644 --- a/Nitrox.Assets.Subnautica/LanguageFiles/hu.json +++ b/Nitrox.Assets.Subnautica/LanguageFiles/hu.json @@ -1,25 +1,25 @@ { "Nitrox_AddServer": "Szerver hozzáadása", - "Nitrox_AddServerAdd": "Hozzáad", - "Nitrox_AddServerHost": "Hoszt:", - "Nitrox_AddServerName": "Név:", - "Nitrox_AddServerPort": "Port:", + "Nitrox_BuildingSettings": "Bázis építés", "Nitrox_Cancel": "Vissza", "Nitrox_CommandNotAvailable": "Ez a parancs nem érhető el a Nitroxon keresztül", "Nitrox_ConnectTo": "Csatlakozás", "Nitrox_DisconnectedSession": "Kilépve a munkamenetből", "Nitrox_DiscordAccept": "Elfogad", "Nitrox_DiscordDecline": "Elutasít", + "Nitrox_DiscordInGame": "{PLAYER} ként játszani", + "Nitrox_DiscordInGameState": "Merülés a mélybe", + "Nitrox_DiscordMainMenuState": "Menüben való bóklászás", + "Nitrox_DiscordMultiplayerMenu": "Kérem nyomja meg a Többjátékos gombot a Főmenüben ha szeretne csatlakozni egy szerverhez", "Nitrox_DiscordPressToFocus": "Nyomd meg a feloldáshoz", "Nitrox_DiscordRequestText": "Engedélyt kértek a játékhoz való csatlakozáshoz", "Nitrox_EnterName": "Játékos neve", + "Nitrox_Failure": "Egy hiba jelent meg", "Nitrox_FirewallInterfering": "Kérlek állítsd át a Tűzfal beállításaidat, hogy működjön a játék", "Nitrox_HideIp": "IP-címek elrejtése", "Nitrox_HidePing": "Ping Elrejtése", "Nitrox_InvalidUserName": "Kérlek, érvényes nevet adj meg!\n\nNem tartalmazhat szóközt, vagy különleges karaktereket!\nMegengedett karakterek: A-Z a-z 0-9 _ . -\nHosszúság: [3, 25]", "Nitrox_Join": "Csatlakozás", - "Nitrox_JoinServerFailed": "Nem sikerült csatlakozni a szerverre", - "Nitrox_JoinServerIpAddress": "Szerver IP cím", "Nitrox_JoinServerPassword": "Jelszó:", "Nitrox_JoinServerPasswordHeader": "A belépéshez jelszó kell", "Nitrox_JoiningSession": "Betöltés többjátékos munkamenetre", @@ -34,10 +34,16 @@ "Nitrox_Mute": "{PLAYER} lenémítása", "Nitrox_MuteQuestion": "Lenémítod {PLAYER} Játékost?", "Nitrox_MutedPlayer": "{PLAYER} Lenémítva", - "Nitrox_PlayerColor": "Játékos színe", + "Nitrox_OutOfDateClient": "A Nitrox telepítésed elavult. Szerver verziója: {serverVersion}, A tiéd: {localVersion}.", + "Nitrox_OutOfDateServer": "A szerver egy régebbi Nitrox verziót használ. Kérje meg a szerver admint hogy frissítse a szervert vagy használjon egy régebbi Nitrox verziót. Szerver verziója: {serverVersion}, A tiéd: {localVersion}.", + "Nitrox_PlayerDied": "{PLAYER} meghalt", + "Nitrox_PlayerDisconnected": "{PLAYER} lecsatlakozott", + "Nitrox_PlayerJoined": "{JÁTÉKOS} csatlakozott a játékhoz.", "Nitrox_PlayerKicked": "Ki lettél rúgva a szerverről", + "Nitrox_PlayerLeft": "{JÁTÉKOS} elhagyta a játékot.", "Nitrox_PlayerListTabName": "Játékos Lista", "Nitrox_RejectedSessionPolicy": "A foglalás elutasítva…", + "Nitrox_RemotePlayerObstacle": "Egy másik játékos vagy a lerombolandó dologban vagy túl közel.", "Nitrox_RequestingSessionPolicy": "Munkamenet szabályok lekérése…", "Nitrox_ServerStopped": "A szerver leállt", "Nitrox_ShowPing": "Ping Mutatása", @@ -45,12 +51,12 @@ "Nitrox_SilencedChatNotif": "A csevegés mostantól néma", "Nitrox_StartServer": "Először indítsd el a szervered, hogy csatlakozni tudj a saját szerveredre", "Nitrox_StreamerSettings": "Streamer mód", - "Nitrox_SubmitPassword": "Jelszó megadása", "Nitrox_SyncingWorld": "Többjátékos világ szinkronizálása…", "Nitrox_TeleportTo": "{PLAYER} játékoshoz teleportálás", "Nitrox_TeleportToMe": "{PLAYER} Játékos magamhoz teleportálása", "Nitrox_TeleportToMeQuestion": "Magamhoz teleportáljam {PLAYER} játékost?", "Nitrox_TeleportToQuestion": "Teleportálni akarsz {PLAYER} játékoshoz?", + "Nitrox_ThankForPlaying": "Köszönjük hogy a Nitrox-ot használod!", "Nitrox_UnableToConnect": "Nem sikerült csatlakozni a megadott távoli szerverre:", "Nitrox_Unmute": "Némítás visszavonása {PLAYER} játékosról", "Nitrox_UnmuteQuestion": "Visszavonod a némítást {PLAYER} Játékosról?", diff --git a/Nitrox.Assets.Subnautica/LanguageFiles/it.json b/Nitrox.Assets.Subnautica/LanguageFiles/it.json index 1879919cc2..fbdbd8c399 100644 --- a/Nitrox.Assets.Subnautica/LanguageFiles/it.json +++ b/Nitrox.Assets.Subnautica/LanguageFiles/it.json @@ -1,68 +1,86 @@ { "Nitrox_AddServer": "Aggiungi un server", - "Nitrox_AddServerAdd": "Aggiungi", - "Nitrox_AddServerHost": "Indirizzo IP:", - "Nitrox_AddServerName": "Nome:", - "Nitrox_AddServerPort": "Porta:", + "Nitrox_BuildingDesyncDetected": "Il server ha rilevato una desincronizzazione con le build del client locale (vai alle impostazioni Nitrox per richiedere una risincronizzazione)", + "Nitrox_BuildingSettings": "Costruzione Di Basi", "Nitrox_Cancel": "Annulla", "Nitrox_CommandNotAvailable": "Questo comando non è disponibile con Nitrox", + "Nitrox_Confirm": "Conferma", "Nitrox_ConnectTo": "Connettiti a", + "Nitrox_DenyOwnershipHand": "Un altro giocatore sta interagendo con quell'oggetto", "Nitrox_DisconnectedSession": "Disconnesso dal server", "Nitrox_DiscordAccept": "Accetta", "Nitrox_DiscordDecline": "Rifiuta", "Nitrox_DiscordInGame": "Sta giocando come {PLAYER}", "Nitrox_DiscordInGameState": "Immergendosi nell'abisso", - "Nitrox_DiscordMainMenuState": "Nascondendosi nel menù", + "Nitrox_DiscordMainMenuState": "Nel menù", "Nitrox_DiscordMultiplayerMenu": "Per favore premi sul pulsante Multiplayer nel menù principale per entrare in una sessione", "Nitrox_DiscordPressToFocus": "Premi per sbloccare", - "Nitrox_DiscordRequestText": "Richiesto di partecipare alla tua sessione", - "Nitrox_EnterName": "Inserisci il nome giocatore", + "Nitrox_DiscordRequestText": "Richiesta di partecipazione alla sessione", + "Nitrox_EnterName": "Inserisci il tuo nickname", + "Nitrox_ErrorDesyncDetected": "[Safe Building] Questa base è attualmente non sincronizzata, quindi non puoi modificarla a meno che non risincronizzi i buildings (nelle impostazioni Nitrox)", + "Nitrox_ErrorRecentBuildUpdate": "Non è possibile modificare una base che è stata recentemente aggiornata da un altro giocatore", "Nitrox_Failure": "Si è verificato un errore", - "Nitrox_FirewallInterfering": "Sembrerebbe che il firewall stia interferendo", + "Nitrox_FinishedResyncRequest": "Sono stati necessari {TIME} ms per risincronizzare {COUNT} entità", + "Nitrox_FirewallInterfering": "Sembra che le tue impostazioni del firewall stiano interferendo", "Nitrox_HideIp": "Nascondi gli indirizzi IP", - "Nitrox_HidePing": "Nascondi ping", - "Nitrox_InvalidUserName": "Inserire un nome di giocatore valido.\n\nNon può contenere spazi o caratteri dubbi.\nCaratteri consentiti: A-Z a-z 0-9 _ . -\nLunghezza: [3, 25]", + "Nitrox_HidePing": "Nascondi Ping", + "Nitrox_IntroUWEPresents": "UNKNOWN WORLDS ENTERTAINMENT\n&\nIL TEAM NITROX\n\nPRESENTANO", + "Nitrox_IntroWaitingPartner": "Un compagno si sta unendo alla sessione\n\nPremi {0} per saltare l’attesa", + "Nitrox_InvalidUserName": "Inserire un nickname valido.\n\nNon può contenere spazi o caratteri ambigui.\nCaratteri consentiti: A-Z a-z 0-9 _ . -\nLunghezza: [3 - 25]", "Nitrox_Join": "Entra", - "Nitrox_JoinServerFailed": "Impossibile entrare nel server", - "Nitrox_JoinServerIpAddress": "Indirizzo IP", + "Nitrox_JoinServer": "Partecipazione:", "Nitrox_JoinServerPassword": "Password:", - "Nitrox_JoinServerPasswordHeader": "Richiesta password", - "Nitrox_JoiningSession": "Sto entrando nella sessione Multigiocatore", + "Nitrox_JoinServerPasswordHeader": "Password del server richiesta", + "Nitrox_JoinServerPlaceholder": "Inserisci la password del server", + "Nitrox_JoiningSession": "Entrando nella Sessione Multigiocatore", "Nitrox_Kick": "Espelli {PLAYER}", - "Nitrox_KickQuestion": "Espellere {PLAYER}?", + "Nitrox_KickQuestion": "Vuoi espellere {PLAYER}?", "Nitrox_LaunchGame": "Caricamento…", "Nitrox_LoadingScreenWarn": "Aspettati problemi che potrebbero compromettere l'esperienza di gioco", "Nitrox_LostConnection": "Connessione al server persa", "Nitrox_LostConnectionWarn": "Non più connesso al server", + "Nitrox_MissingPermission": "Non hai l'autorizzazione per eseguire questo comando [{PERMISSION}]", "Nitrox_Multiplayer": "Multigiocatore", "Nitrox_MultiplayerLoaded": "Client multigiocatore caricato…", "Nitrox_Mute": "Muta {PLAYER}", - "Nitrox_MuteQuestion": "Muta {PLAYER}?", - "Nitrox_MutedPlayer": "Mutato {PLAYER}", - "Nitrox_PlayerColor": "Colore giocatore", + "Nitrox_MuteQuestion": "Vuoi mutare {PLAYER}?", + "Nitrox_MutedPlayer": "Hai mutato {PLAYER}", + "Nitrox_OK": "Ok", + "Nitrox_OutOfDateClient": "La tua installazione di Nitrox non è aggiornata. Server: {serverVersion}, Versione: {localVersion}.", + "Nitrox_OutOfDateServer": "Il server esegue una versione precedente di Nitrox. Chiedi all'amministratore del server di aggiornare il server o eseguire il downgrade della tua installazione Nitrox. Server: {serverVersion}, Versione: {localVersion}.", + "Nitrox_PlayerDied": "{PLAYER} è morto", + "Nitrox_PlayerDisconnected": "{PLAYER} disconnesso", + "Nitrox_PlayerJoined": "{PLAYER} si è unito alla sessione.", "Nitrox_PlayerKicked": "Sei stato espulso dal server", + "Nitrox_PlayerLeft": "{PLAYER} ha lasciato la sessione.", "Nitrox_PlayerListTabName": "Elenco giocatori", "Nitrox_RejectedSessionPolicy": "Richiesta rifiutata…", - "Nitrox_RequestingSessionPolicy": "Richiesta di informazioni sui criteri di sessione…", - "Nitrox_ServerStopped": "Il server è stato fermato", - "Nitrox_ShowPing": "Mostra ping", - "Nitrox_SilenceChat": "Disattiva la discussione", - "Nitrox_SilencedChatNotif": "La chat è ora silenziata", - "Nitrox_StartServer": "Per entrare nel tuo server locale devi prima avviarlo da Nitrox Launcher", - "Nitrox_StreamerSettings": "Modalità streamer", - "Nitrox_SubmitPassword": "Conferma", + "Nitrox_RemotePlayerObstacle": "Un altro giocatore è all'interno o troppo vicino al bersaglio da smantellare.", + "Nitrox_RequestingSessionPolicy": "Richiedendo informazioni sui criteri di sessione…", + "Nitrox_ResyncBuildings": "Ri-Sincronizza Edifici Delle Basi", + "Nitrox_ResyncOnCooldown": "Devi attendere {TIME_LEFT} secondi per inviare un'altra richiesta di risincronizzazione", + "Nitrox_ResyncRequested": "Emessa una richiesta di sincronizzazione per le basi", + "Nitrox_ResyncSettings": "Risincronizzazione", + "Nitrox_SafeBuilding": "Costruzione Sicura", + "Nitrox_SafeBuildingLog": "Registro Costruzione Sicura", + "Nitrox_ServerStopped": "Il server si è arrestato", + "Nitrox_ShowPing": "Mostra Ping", + "Nitrox_SilenceChat": "Disattiva chat", + "Nitrox_SilencedChatNotif": "La chat è stata disattivata", + "Nitrox_StartServer": "Per entrare nel mondo avvia prima il tuo server", + "Nitrox_StreamerSettings": "Modalità Streamer", "Nitrox_SyncingWorld": "Sincronizzazione del mondo multiplayer…", - "Nitrox_TeleportTo": "Teletrasporta su {PLAYER}", + "Nitrox_TeleportTo": "Teletrasportati da {PLAYER}", "Nitrox_TeleportToMe": "Teletrasporta {PLAYER} da me", - "Nitrox_TeleportToMeQuestion": "Teletrasportare {PLAYER} da me ?", - "Nitrox_TeleportToQuestion": "Teletrasportarsi su {PLAYER}?", + "Nitrox_TeleportToMeQuestion": "Teletrasportare {PLAYER} da me?", + "Nitrox_TeleportToQuestion": "Teletrasportarsi da {PLAYER}?", "Nitrox_ThankForPlaying": "Grazie per aver scelto Nitrox!", "Nitrox_UnableToConnect": "Impossibile contattare il server:", - "Nitrox_Unmute": "Non mutato {PLAYER}", - "Nitrox_UnmuteQuestion": "Non mutare {PLAYER}?", - "Nitrox_UnmutedPlayer": "Non mutato {PLAYER}", - "Nitrox_Waiting": "In attesa in coda di iscrizione…", + "Nitrox_Unmute": "Attiva l'audio di {PLAYER}", + "Nitrox_UnmuteQuestion": "Attivare l'audio di {PLAYER}?", + "Nitrox_UnmutedPlayer": "L'audio di {PLAYER} è stato attivato", + "Nitrox_Waiting": "In attesa in coda…", "Nitrox_WaitingPassword": "In attesa della password per il server…", - "Nitrox_WaitingUserInput": "In attesa dell'inserimento dal parte dell'utente…", - "Nitrox_WorldSettling": "In attesa impostazioni del mondo…" + "Nitrox_WaitingUserInput": "In attesa dell'inserimento da parte dell'utente…", + "Nitrox_WorldSettling": "In attesa della stabilizzazione del mondo…" } diff --git a/Nitrox.Assets.Subnautica/LanguageFiles/ja.json b/Nitrox.Assets.Subnautica/LanguageFiles/ja.json index 0967ef424b..b7b54f67cb 100644 --- a/Nitrox.Assets.Subnautica/LanguageFiles/ja.json +++ b/Nitrox.Assets.Subnautica/LanguageFiles/ja.json @@ -1 +1,77 @@ -{} +{ + "Nitrox_AddServer": "サーバーを追加する", + "Nitrox_BuildingDesyncDetected": "サーバーがローカルクライアントの建物との非同期を検出しました(Nitroxの設定で再同期をしてください)", + "Nitrox_Cancel": "キャンセル", + "Nitrox_CommandNotAvailable": "Nitroxではこのコマンドは使用できません", + "Nitrox_ConnectTo": "〜に接続する", + "Nitrox_DisconnectedSession": "サーバーから切断されました", + "Nitrox_DiscordAccept": "受け入れる", + "Nitrox_DiscordDecline": "断る", + "Nitrox_DiscordInGame": "{PLAYER}としてプレイする", + "Nitrox_DiscordInGameState": "深淵に潜る", + "Nitrox_DiscordMainMenuState": "メニューの中に潜んでいる", + "Nitrox_DiscordMultiplayerMenu": "セッションに参加したければメインメニューにあるマルチプレイヤーボタンを押してください", + "Nitrox_DiscordPressToFocus": "押してアンロックする", + "Nitrox_DiscordRequestText": "貴方のセッションに参加したいというリクエストあり", + "Nitrox_EnterName": "貴方のプレイヤーネームを入力してください", + "Nitrox_ErrorDesyncDetected": "[安全な建物]この基地は現在同期が解除されているため、Nitroxの設定で建物を再同期しない限り、変更することはできません", + "Nitrox_ErrorRecentBuildUpdate": "他のプレイヤーが最近更新したベースは変更することができません", + "Nitrox_Failure": "エラーが生じました", + "Nitrox_FinishedResyncRequest": "COUNT}エンティティの再同期に{TIME}msかかりました", + "Nitrox_FirewallInterfering": "どうやら貴方のファイヤーウォールの設定が邪魔しているようです", + "Nitrox_HideIp": "IPアドレスを隠す", + "Nitrox_HidePing": "ピングを隠す", + "Nitrox_InvalidUserName": "正しいプレイヤーネームを入力してください\n\nスペースや問題のある文字は使えません\n可能な文字:A-Z a-z 0-9\n長さ:[3, 25]", + "Nitrox_Join": "参加する", + "Nitrox_JoinServerPassword": "パスワード:", + "Nitrox_JoinServerPasswordHeader": "サーバーのパスワードが必要です", + "Nitrox_JoiningSession": "マルチプレイのセッションに参加中", + "Nitrox_Kick": "{PLAYER}を退出させる", + "Nitrox_KickQuestion": "{PLAYER}を退出させますか?", + "Nitrox_LaunchGame": "ゲームを開始中…", + "Nitrox_LoadingScreenWarn": "ゲームを中断させるようなバグがあります", + "Nitrox_LostConnection": "ゲームサーバーとの接続が失われました", + "Nitrox_LostConnectionWarn": "もはやサーバーには接続されていません", + "Nitrox_Multiplayer": "マルチプレイヤー", + "Nitrox_MultiplayerLoaded": "マルチプレイのクライアントがロードされました…", + "Nitrox_Mute": "{PLAYER}をミュートにする", + "Nitrox_MuteQuestion": "{PLAYER}をミュートにしますか?", + "Nitrox_MutedPlayer": "{PLAYER}ミュート状態", + "Nitrox_OutOfDateClient": "現在あなたがインストールしているNitroxバージョンが古いようです。サーバーのバージョン:{serverVersion},あなたがインストールしているバージョン:{localVersion}。", + "Nitrox_OutOfDateServer": "サーバーのNitroxバージョンが古いようです。サーバー管理者にサーバーのアップグレードを要求するか、Nitroxのバージョンをダウングレードしてください。サーバーのバージョン:{severVersion},あなたがインストールしているバージョン:{localVersion}", + "Nitrox_PlayerDied": "{PLAYER}は死亡した", + "Nitrox_PlayerDisconnected": "{PLAYER}が退出した", + "Nitrox_PlayerJoined": "{PLAYER}がゲームに参加した。", + "Nitrox_PlayerKicked": "貴方はサーバーから退出させられました", + "Nitrox_PlayerLeft": "{PLAYER}退場した。", + "Nitrox_PlayerListTabName": "プレイヤーリスト", + "Nitrox_RejectedSessionPolicy": "予約が拒否されました…", + "Nitrox_RemotePlayerObstacle": "他のプレイヤーが分解可能なターゲットの中にいるか、近すぎます。", + "Nitrox_RequestingSessionPolicy": "セッションのポリシー情報を要求中…", + "Nitrox_ResyncBuildings": "ベースとなる建物の再同期", + "Nitrox_ResyncOnCooldown": "再同期リクエストができるようになるまであと{TIME_LEFT}秒", + "Nitrox_ResyncRequested": "ベースの再同期リクエストを発行", + "Nitrox_ResyncSettings": "再同期", + "Nitrox_SafeBuilding": "安全な建物", + "Nitrox_SafeBuildingLog": "安全な建物のログ", + "Nitrox_ServerStopped": "サーバーが停止中", + "Nitrox_ShowPing": "ピングを表示する", + "Nitrox_SilenceChat": "チャットをミュートにする", + "Nitrox_SilencedChatNotif": "チャットは現在ミュート中", + "Nitrox_StartServer": "自らがホストとなる世界に参加するためには、まず自分のサーバーを開始してください", + "Nitrox_StreamerSettings": "ストリーマーモード", + "Nitrox_SyncingWorld": "マルチプレイの世界を同期中…", + "Nitrox_TeleportTo": "{PLAYER}のところにテレポートする", + "Nitrox_TeleportToMe": "{PLAYER}を自分のところにテレポートする", + "Nitrox_TeleportToMeQuestion": "{PLAYER}を自分のところにテレポートしますか?", + "Nitrox_TeleportToQuestion": "{PLAYER}のところにテレポートしますか?", + "Nitrox_ThankForPlaying": "Nitroxをご使用頂きありがとうございます!", + "Nitrox_UnableToConnect": "リモートサーバーにコンタクトできません:", + "Nitrox_Unmute": "{PLAYER}のミュートを解除", + "Nitrox_UnmuteQuestion": "{PLAYER}のミュートを解除しますか?", + "Nitrox_UnmutedPlayer": "{PLAYER}のミュートが解除されました", + "Nitrox_Waiting": "参加の順番待ち中…", + "Nitrox_WaitingPassword": "サーバーパスワードの入力待ち…", + "Nitrox_WaitingUserInput": "ユーザーの入力待ち…", + "Nitrox_WorldSettling": "世界の確定を待機中…" +} diff --git a/Nitrox.Assets.Subnautica/LanguageFiles/ko.json b/Nitrox.Assets.Subnautica/LanguageFiles/ko.json index fff19d34bd..b3f113e123 100644 --- a/Nitrox.Assets.Subnautica/LanguageFiles/ko.json +++ b/Nitrox.Assets.Subnautica/LanguageFiles/ko.json @@ -1,48 +1,70 @@ { "Nitrox_AddServer": "서버 추가", - "Nitrox_AddServerAdd": "추가", - "Nitrox_AddServerHost": "주인:", - "Nitrox_AddServerName": "이름:", - "Nitrox_AddServerPort": "포트:", "Nitrox_Cancel": "취소", "Nitrox_CommandNotAvailable": "이 명령어는 Nitrox에서 사용할 수 없습니다", + "Nitrox_Confirm": "확인", "Nitrox_ConnectTo": "연결", + "Nitrox_DenyOwnershipHand": "다른 플레이어가 해당 물체와 상호작용중입니다", "Nitrox_DisconnectedSession": "서버와의 연결이 끊어졌습니다", "Nitrox_DiscordAccept": "수락", "Nitrox_DiscordDecline": "거절", + "Nitrox_DiscordInGame": "{PLAYER} 로 플레이 중", + "Nitrox_DiscordMultiplayerMenu": "세션에 참가하려면 메인메뉴에 있는 멀티플레이어 버튼을 누르십시오", "Nitrox_DiscordPressToFocus": "눌러서 열기", "Nitrox_DiscordRequestText": "세션 참가 요청", - "Nitrox_EnterName": "니 이름 적어", + "Nitrox_EnterName": "플레이어 이름을 입력해주세요", + "Nitrox_ErrorRecentBuildUpdate": "최근에 다른 플레이어가 기지를 편집했기 때문에 편집할 수 없습니다", + "Nitrox_Failure": "오류가 발생했습니다", "Nitrox_FirewallInterfering": "방화벽 설정이 방해하는 것처럼 보임", "Nitrox_HideIp": "IP 숨기기", "Nitrox_HidePing": "핑 숨기기", - "Nitrox_InvalidUserName": "올바른 플레이어 이름을 입력하십시오.\n\n공백이나 의심스러운 문자를 포함할 수 없습니다\n사용 가능한 문자: A-Z a-z 0-9 _ . -\n길이: [3, 25]", + "Nitrox_IntroUWEPresents": "UNKNOWN WORLD ENTERTAINMENT\n&\nTHE NITROX-TEAM\n\n제공", + "Nitrox_IntroWaitingPartner": "플레이어가 참가할때까지 대기중\n\n {0} 을 눌러 대기 넘기기", + "Nitrox_InvalidUserName": "올바른 플레이어 이름을 입력하십시오.\n\n공백이나 특수문자를 포함할 수 없습니다\n사용 가능한 문자: A-Z a-z 0-9 _ . -\n길이: [3, 25]", "Nitrox_Join": "접속", - "Nitrox_JoinServerFailed": "서버에 접속할 수 없음", - "Nitrox_JoinServerIpAddress": "서버 IP", + "Nitrox_JoinServer": "참가중:", "Nitrox_JoinServerPassword": "비밀번호:", "Nitrox_JoinServerPasswordHeader": "서버 비밀번호 필요", + "Nitrox_JoinServerPlaceholder": "비밀번호를 입력하십시오", "Nitrox_JoiningSession": "멀티플레이어 세션 참가중", + "Nitrox_Kick": "{PLAYER} 추방", + "Nitrox_KickQuestion": "{PLAYER} 을(를) 추방하시겠습니까?", "Nitrox_LaunchGame": "게임 시작중…", "Nitrox_LoadingScreenWarn": "게임 파괴 버그 예상", "Nitrox_LostConnection": "서버와의 연결이 끊어졌습니다", "Nitrox_LostConnectionWarn": "서버에 더 이상 연결되지 않음", + "Nitrox_MissingPermission": "이 명령어를 실행할 수 있는 권한이 없습니다 [{PERMISSION}]", "Nitrox_Multiplayer": "멀티플레이어", "Nitrox_MultiplayerLoaded": "멀티플레이어 클라이언트 로드…", - "Nitrox_PlayerColor": "플레이어 색상", + "Nitrox_Mute": "{PLAYER} 음소거", + "Nitrox_MuteQuestion": "{PLAYER}를 음소거하시겠습니까?", + "Nitrox_MutedPlayer": "{PLAYER} 음소거됨", + "Nitrox_PlayerDied": "{PLAYER} 죽었습니다", + "Nitrox_PlayerDisconnected": "{PLAYER} 연결 끊김", + "Nitrox_PlayerJoined": "{PLAYER} 가 게임에 참가하였습니다", "Nitrox_PlayerKicked": "서버에서 추방당했습니다", + "Nitrox_PlayerLeft": "{PLAYER} 퇴장함", "Nitrox_PlayerListTabName": "플레이어 리스트", "Nitrox_RejectedSessionPolicy": "예약 거부됨…", + "Nitrox_RemotePlayerObstacle": "다른 플레이어가 목표 안에 있거나 너무 가깝습니다", "Nitrox_RequestingSessionPolicy": "세션 정책 정보를 요청하는 중…", - "Nitrox_ServerStopped": "서버가 종료되었습니다.", + "Nitrox_ResyncOnCooldown": "다른 리싱크 요청을 보내기 위해선 {TIME_LEFT} 를 기다려야 합니다", + "Nitrox_ServerStopped": "서버가 종료되었습니다", "Nitrox_ShowPing": "핑 표시", "Nitrox_SilenceChat": "채팅 음소거", "Nitrox_SilencedChatNotif": "채팅이 음소거되었습니다", "Nitrox_StartServer": "서버를 먼저 시작하여 자체 호스트에 참여", "Nitrox_StreamerSettings": "방송 모드", - "Nitrox_SubmitPassword": "제출", "Nitrox_SyncingWorld": "멀티플레이어 세계 동기화…", + "Nitrox_TeleportTo": "{PLAYER} 에게 텔레포트", + "Nitrox_TeleportToMe": "{PLAYER} 를 나에게 텔레포트", + "Nitrox_TeleportToMeQuestion": "{PLAYER} 를 나에게 순간이동 시키겠습니까?", + "Nitrox_TeleportToQuestion": "{PLAYER} 에게 순간이동하겠습니까?", + "Nitrox_ThankForPlaying": "Nitrox 를 이용해주셔서 감사합니다!", "Nitrox_UnableToConnect": "원격 서버에 연결할 수 없음:", + "Nitrox_Unmute": "{PLAYER} 음소거 해제", + "Nitrox_UnmuteQuestion": "{PLAYER} 음소거를 해제하겠습니까?", + "Nitrox_UnmutedPlayer": "{PLAYER} 음소거 해제됨", "Nitrox_Waiting": "접속 대기 중…", "Nitrox_WaitingPassword": "서버 비밀번호 입력을 기다리는 중…", "Nitrox_WaitingUserInput": "유저 입력을 기다리는 중…", diff --git a/Nitrox.Assets.Subnautica/LanguageFiles/lt.json b/Nitrox.Assets.Subnautica/LanguageFiles/lt.json index d8ba9222e3..e05045563b 100644 --- a/Nitrox.Assets.Subnautica/LanguageFiles/lt.json +++ b/Nitrox.Assets.Subnautica/LanguageFiles/lt.json @@ -1,21 +1,86 @@ { - "Nitrox_AddServer": "Pridėti tinklą", - "Nitrox_AddServerAdd": "Pridėti", - "Nitrox_AddServerHost": "Sukurti:", - "Nitrox_AddServerName": "Vardas", + "Nitrox_AddServer": "Pridėti serverį", + "Nitrox_BuildingDesyncDetected": "Serveris aptiko sinchronizacijos klaidą žaidėjo kliento programoje(Eikite į Nitrox parametrus ir atlikite resinchronizaciją)", + "Nitrox_BuildingSettings": "Bazės statymas", "Nitrox_Cancel": "Atšaukti", "Nitrox_CommandNotAvailable": "Ši komanda Nitrox papildinyje nepasiekiama", + "Nitrox_Confirm": "Patvirtinimas", "Nitrox_ConnectTo": "Prisijungti prie", - "Nitrox_DisconnectedSession": "Atsijungti", + "Nitrox_DenyOwnershipHand": "Kitas žaidėjas šiuo metu žiūri šį objektą", + "Nitrox_DisconnectedSession": "Atjungtas nuo serverio", "Nitrox_DiscordAccept": "Sutikti", "Nitrox_DiscordDecline": "Atšaukti", + "Nitrox_DiscordInGame": "Žaidžiama kaip {PLAYER}", + "Nitrox_DiscordInGameState": "Panirimas į bedugnę", + "Nitrox_DiscordMainMenuState": "Laukiama ant meniu ekrano", + "Nitrox_DiscordMultiplayerMenu": "Prašome paspausti Multiplayer mygtuką MainMenu lange, norint prisijungti į sesiją", "Nitrox_DiscordPressToFocus": "Spauskite kad atrakinti", "Nitrox_DiscordRequestText": "Prašo leidimo prisijungti", "Nitrox_EnterName": "Įveskite savo žaidėjo vardą", + "Nitrox_ErrorDesyncDetected": "(Saugus statymas) Ši bazė yra desinchronizuota, todėl negali būti keičiama, nebent bus resinchronizuoti pastatai( Nitrox parametruose)", + "Nitrox_ErrorRecentBuildUpdate": "Bazė negali būti keičiama, nes ją ką tik keitė kitas žaidėjas", + "Nitrox_Failure": "Atsitiko klaida", + "Nitrox_FinishedResyncRequest": "Užtruko(laiko) ms resinchronizuoti(suskaičiuoti) elementus", "Nitrox_FirewallInterfering": "Atrodo kad, jūsų apsaugos nustatymai trukdo", "Nitrox_HideIp": "Slėpti IP adresus", "Nitrox_HidePing": "Slėpti Ping", - "Nitrox_InvalidUserName": "Prašome įvesti veikianti slapyvardį.\n\nJame negali būti tarpų arba kitokių ženklų.\nLeistini simboliai:A-Z a-z 0-9 _ . -\nIlgis: [3, 25]", + "Nitrox_IntroUWEPresents": "UNKNOWN WORLD ENTERTAINMENTS\n\nNITROX-TEAM\n\nPRISTATO", + "Nitrox_IntroWaitingPartner": "Laukiama kol prisijungs kitas žaidėjas\n\nSpauskite {0}, kad nelaukti", + "Nitrox_InvalidUserName": "Prašome įvesti veikianti slapyvardį.\n\nJame negali būti tarpų arba kitokių ženklų.\nLeistini simboliai:A-Z a-z 0-9 _ . -\nIlgis: [3, 25]", "Nitrox_Join": "Prisijungti", - "Nitrox_JoinServerFailed": "Ivyko klaida" + "Nitrox_JoinServer": "Prisijungiama:", + "Nitrox_JoinServerPassword": "Slaptažodis:", + "Nitrox_JoinServerPasswordHeader": "Serverio slaptažodis reikalingas", + "Nitrox_JoinServerPlaceholder": "Įveskite serverio slaptažodį", + "Nitrox_JoiningSession": "Prisijungiama į Multiplayer sesiją", + "Nitrox_Kick": "Išmesti {PLAYER}", + "Nitrox_KickQuestion": "Išmesti {PLAYER}?", + "Nitrox_LaunchGame": "Paleidžiamas žaidimas…", + "Nitrox_LoadingScreenWarn": "Tikėkites Žaidimą-sugadinančių klaidų", + "Nitrox_LostConnection": "Praradome ryšį su žaidimo serveriu", + "Nitrox_LostConnectionWarn": "Nebe prisijungę prie serverio", + "Nitrox_MissingPermission": "Neturite leidimo paleisti šios komandos [{PERMISSION}]", + "Nitrox_Multiplayer": "Žaisti su kitais", + "Nitrox_MultiplayerLoaded": "Žaidimo kartu clientas užkrautas…", + "Nitrox_Mute": "Užtildyti {PLAYER}", + "Nitrox_MuteQuestion": "Užtildyti {PLAYER}?", + "Nitrox_MutedPlayer": "Užtildytas {PLAYER}", + "Nitrox_OK": "Ok", + "Nitrox_OutOfDateClient": "Nitrox instaliacija nebegalioja. Ją reikia atnaujinti. Server: {serverVersion}, Yours: {localVersion}.", + "Nitrox_OutOfDateServer": "Serveris naudoja senesnę Nitrox versiją. Prašykit serverio administratoriaus atnaujinti severio versiją arba sumažinkit savo Nitrox versiją. Server: {serverVersion}, Yours: {localVersion}.", + "Nitrox_PlayerDied": "{PLAYER} Mirė", + "Nitrox_PlayerDisconnected": "{PLAYER} Atsijungė", + "Nitrox_PlayerJoined": "{PLAYER} prisijungė į žaidimą.", + "Nitrox_PlayerKicked": "Jūs buvote išmestas iš serverio", + "Nitrox_PlayerLeft": "{PLAYER} atsijungė iš žaidimo.", + "Nitrox_PlayerListTabName": "Žaidėjų sąrašas", + "Nitrox_RejectedSessionPolicy": "Rezervacija atmesta…", + "Nitrox_RemotePlayerObstacle": "Kitas žaidėjas arba viduje arba per arti išmontuojamo objekto.", + "Nitrox_RequestingSessionPolicy": "Prašoma sesijos politikos informacijos…", + "Nitrox_ResyncBuildings": "Resinchronizuoti bazės statinius", + "Nitrox_ResyncOnCooldown": "Turite palaukti(TIME_LEFT) sekundžių, kad būtų galima siųsti kitą resinchronizacijos prašymą", + "Nitrox_ResyncRequested": "Buvo įvykdyta bazių/bazės resinchronizacija", + "Nitrox_ResyncSettings": "Resinchronizacija", + "Nitrox_SafeBuilding": "Saugus statymas", + "Nitrox_SafeBuildingLog": "Saugaus statymo sąrašas", + "Nitrox_ServerStopped": "Serveris buvo sustabdytas", + "Nitrox_ShowPing": "Parodyti Ping", + "Nitrox_SilenceChat": "Užtildyti rašymo lauką", + "Nitrox_SilencedChatNotif": "Rašymo laukas užtildytas", + "Nitrox_StartServer": "Pirma startuokite savo serverį, kad prisijungtumete prie savo paleisto pasaulio", + "Nitrox_StreamerSettings": "Filmuotojo rėžimas", + "Nitrox_SyncingWorld": "Sinchronizuojamas multiplayer pasaulis…", + "Nitrox_TeleportTo": "Teleportuotis pas {PLAYER}", + "Nitrox_TeleportToMe": "Teleportuoti {PLAYER} pas mane", + "Nitrox_TeleportToMeQuestion": "Teleportuoti {PLAYER} pas mane?", + "Nitrox_TeleportToQuestion": "Teleportuotis pas {PLAYER}?", + "Nitrox_ThankForPlaying": "Ąčiū, kad naudojate Nitrox!", + "Nitrox_UnableToConnect": "Nėra galimybės susisiekti su nuotoliniu serveriu adresu:", + "Nitrox_Unmute": "Atšaukti užtildymą", + "Nitrox_UnmuteQuestion": "Atšaukti užtildymą?", + "Nitrox_UnmutedPlayer": "Atšauktas užtildymas {PLAYER}", + "Nitrox_Waiting": "Laukiama prisijungimo eilėje…", + "Nitrox_WaitingPassword": "Laukiama serverio slaptažodžio įrašymo…", + "Nitrox_WaitingUserInput": "Laukiama vartotojo įrąšymo…", + "Nitrox_WorldSettling": "Laukiama pasaulio nusėdimo…" } diff --git a/Nitrox.Assets.Subnautica/LanguageFiles/lv.json b/Nitrox.Assets.Subnautica/LanguageFiles/lv.json index 2ea2156bf2..e0377317d9 100644 --- a/Nitrox.Assets.Subnautica/LanguageFiles/lv.json +++ b/Nitrox.Assets.Subnautica/LanguageFiles/lv.json @@ -1,3 +1,13 @@ { - "Nitrox_AddServer": "Pievienot Serveri" + "Nitrox_AddServer": "Pievienot Serveri", + "Nitrox_BuildingSettings": "Bāzes būvēšana", + "Nitrox_Cancel": "Atcelt", + "Nitrox_CommandNotAvailable": "Šī komanda nav pieejama uz Nitrox", + "Nitrox_ConnectTo": "Savienoties ar", + "Nitrox_DisconnectedSession": "Atvienots no servera", + "Nitrox_DiscordAccept": "Pieņemt", + "Nitrox_DiscordDecline": "Atteikt", + "Nitrox_DiscordInGame": "Spēlē kā {PLAYER}", + "Nitrox_DiscordInGameState": "Ņurko iekšā bezdibenī", + "Nitrox_DiscordPressToFocus": "Uzspied lai atslēgtu" } diff --git a/Nitrox.Assets.Subnautica/LanguageFiles/nl.json b/Nitrox.Assets.Subnautica/LanguageFiles/nl.json index 9354a27da1..8dee645607 100644 --- a/Nitrox.Assets.Subnautica/LanguageFiles/nl.json +++ b/Nitrox.Assets.Subnautica/LanguageFiles/nl.json @@ -1,48 +1,81 @@ { "Nitrox_AddServer": "Server toevoegen", - "Nitrox_AddServerAdd": "Toevoegen", - "Nitrox_AddServerHost": "Host:", - "Nitrox_AddServerName": "Naam:", - "Nitrox_AddServerPort": "Port:", + "Nitrox_BuildingDesyncDetected": "Synchronisatie probleem gedetecteerd in basis gebouwen (ga naar Nitrox instellingen om basissen opnieuw in te laden)", + "Nitrox_BuildingSettings": "Basis bouwen", "Nitrox_Cancel": "Annuleer", "Nitrox_CommandNotAvailable": "Dit commando is niet beschikbaar in Nitrox", "Nitrox_ConnectTo": "Verbinden met", + "Nitrox_DenyOwnershipHand": "Een andere speler gebruikt dit object", "Nitrox_DisconnectedSession": "U heeft de server verlaten", "Nitrox_DiscordAccept": "Accepteren", "Nitrox_DiscordDecline": "Afwijzen", + "Nitrox_DiscordInGame": "Speelt als {PLAYER}", + "Nitrox_DiscordInGameState": "Duikt naar de zeebodem", + "Nitrox_DiscordMainMenuState": "Kijkt naar het menu", + "Nitrox_DiscordMultiplayerMenu": "Druk op de Multiplayer knop in het hoofdmenu als je een sessie wilt betreden", "Nitrox_DiscordPressToFocus": "Druk om te ontgrendelen", - "Nitrox_DiscordRequestText": "Verzoekt aan Uw sessie deel te nemen", - "Nitrox_EnterName": "Speler Naam", + "Nitrox_DiscordRequestText": "Verzoekt aan je sessie deel te nemen", + "Nitrox_EnterName": "Voer je spelersnaam in", + "Nitrox_ErrorDesyncDetected": "[Veilig bouwen] Deze basis kan niet aangepast worden omdat er synchronisatie problemen zijn. Forceer een synchronisatie in de Nitrox instellingen", + "Nitrox_ErrorRecentBuildUpdate": "Deze basis kan niet bewerkt worden omdat een andere speler dat recent heeft gedaan", + "Nitrox_Failure": "Er is een fout opgetreden", + "Nitrox_FinishedResyncRequest": "Het duurde {TIME}ms om {COUNT} entiteiten opnieuw te synchroniseren", "Nitrox_FirewallInterfering": "Het lijkt erop dat je firewall instellingen het netwerk onderbreken", "Nitrox_HideIp": "IPs verschuilen", "Nitrox_HidePing": "Ping Verbergen", - "Nitrox_InvalidUserName": "Voer een geldige spelernaam in !\n\n Het mag geen spatie of speciale karakters bevatten\n Toegestane karakters : A-Z a-z 0-9 _ . -\nLengte : [3, 25]", + "Nitrox_IntroUWEPresents": "UNKNOWN WORLDS ENTERTAINMENT\n&\nHET NITROX-TEAM\n\nPRESENTEREN", + "Nitrox_IntroWaitingPartner": "Wachten op een partner\n\nKlik {0} om wachten over te slaan", + "Nitrox_InvalidUserName": "Voer een geldige spelernaam in.\n\n Het mag geen spatie of speciale karakters bevatten\n Toegestane karakters : A-Z a-z 0-9 _ . -\nLengte : [3, 25]", "Nitrox_Join": "Meedoen", - "Nitrox_JoinServerFailed": "Kan niet verbinden met server", - "Nitrox_JoinServerIpAddress": "Server IP", "Nitrox_JoinServerPassword": "Wachtwoord:", "Nitrox_JoinServerPasswordHeader": "Server wachtwoord vereist", "Nitrox_JoiningSession": "Meedoen aan multiplayer Sessie", + "Nitrox_Kick": "Kick {PLAYER}", + "Nitrox_KickQuestion": "{PLAYER} uit sessie verwijderen?", "Nitrox_LaunchGame": "Spel opstarten…", "Nitrox_LoadingScreenWarn": "Verwacht spel-brekende bugs", - "Nitrox_LostConnection": "Connectie met de server verloren", + "Nitrox_LostConnection": "Verbinding met de server verloren", "Nitrox_LostConnectionWarn": "Niet meer verbonden met de server", "Nitrox_Multiplayer": "Multiplayer", "Nitrox_MultiplayerLoaded": "Multiplayer client geladen…", - "Nitrox_PlayerColor": "Speler Kleur", + "Nitrox_Mute": "Demp {PLAYER}", + "Nitrox_MuteQuestion": "Demp {PLAYER}?", + "Nitrox_MutedPlayer": "{PLAYER} Gedempt", + "Nitrox_OutOfDateClient": "Je Nitrox-installatie is verouderd. Serverversie: {serverVersion}, Jouw versie: {localVersion}.", + "Nitrox_OutOfDateServer": "Deze server gebruikt een oudere versie van Nitrox. Vraag de serverbeheerder om de server te upgraden, of downgrade jouw Nitrox-installatie. Serverversie: {serverVersion}, Jouw versie: {localVersion}.", + "Nitrox_PlayerDied": "{PLAYER} stierf", + "Nitrox_PlayerDisconnected": "{PLAYER} verbrak de verbinding", + "Nitrox_PlayerJoined": "{PLAYER} is het spel betreden.", "Nitrox_PlayerKicked": "Je bent van de server getrapt", + "Nitrox_PlayerLeft": "{PLAYER} heeft het spel verlaten.", + "Nitrox_PlayerListTabName": "Speler lijst", "Nitrox_RejectedSessionPolicy": "Sessie geweigerd…", + "Nitrox_RemotePlayerObstacle": "Een andere speler is te dicht of bevind zich in een deconstrueerbaar doelwit.", "Nitrox_RequestingSessionPolicy": "Beleid van de sessie aanvragen…", + "Nitrox_ResyncBuildings": "Hersynchroniseer basisgebouwen", + "Nitrox_ResyncOnCooldown": "U moet {TIME_LEFT} seconden wachten om een hersynchronisatieverzoek te sturen", + "Nitrox_ResyncRequested": "Een hersynchronisatieverzoek is ingediend voor je basis", + "Nitrox_ResyncSettings": "Synchronisatie", + "Nitrox_SafeBuilding": "Veilig bouwen", + "Nitrox_SafeBuildingLog": "Basis log opslaan", "Nitrox_ServerStopped": "Server is gestopt", + "Nitrox_ShowPing": "Laat ping zien", "Nitrox_SilenceChat": "Chat dempen", "Nitrox_SilencedChatNotif": "Chat is gedempt", "Nitrox_StartServer": "Start je server eerst om mee toe doen met je eigen gehostte wereld", "Nitrox_StreamerSettings": "Streamer modus", - "Nitrox_SubmitPassword": "Verzenden", "Nitrox_SyncingWorld": "Multiplayer Wereld Synchroniseren…", + "Nitrox_TeleportTo": "Teleporteer naar {PLAYER}", + "Nitrox_TeleportToMe": "Teleporteer {PLAYER} naar mij", + "Nitrox_TeleportToMeQuestion": "Teleporteer {PLAYER} naar mij?", + "Nitrox_TeleportToQuestion": "Teleporteer naar {PLAYER}?", + "Nitrox_ThankForPlaying": "Bedankt voor het spelen met de mod!", "Nitrox_UnableToConnect": "Kan niet verbinden met de externe server op:", + "Nitrox_Unmute": "Dempen opheffen voor {PLAYER}", + "Nitrox_UnmuteQuestion": "Dempen opheffen voor {PLAYER}?", + "Nitrox_UnmutedPlayer": "Dempen opgehoffen voor {PLAYER}", "Nitrox_Waiting": "Wachtend om mee te doen…", "Nitrox_WaitingPassword": "Wachtend op invoer van de server…", "Nitrox_WaitingUserInput": "Wachtend op invoer van de gebruiker…", - "Nitrox_WorldSettling": "Wachtend op ruststand van spel wereld…" + "Nitrox_WorldSettling": "De wereldinstellingen worden afgewacht…" } diff --git a/Nitrox.Assets.Subnautica/LanguageFiles/no.json b/Nitrox.Assets.Subnautica/LanguageFiles/no.json index 8ac4cfbcba..a266544620 100644 --- a/Nitrox.Assets.Subnautica/LanguageFiles/no.json +++ b/Nitrox.Assets.Subnautica/LanguageFiles/no.json @@ -1,46 +1,81 @@ { "Nitrox_AddServer": "Legg til tjener", - "Nitrox_AddServerAdd": "Legg til", - "Nitrox_AddServerHost": "Vert:", - "Nitrox_AddServerName": "Navn:", - "Nitrox_AddServerPort": "Port:", + "Nitrox_BuildingDesyncDetected": "Server oppdaget desynkronisering med lokal klients bygninger (gå til Nitrox instillinger og be om resynkronisering)", + "Nitrox_BuildingSettings": "Base bygging", "Nitrox_Cancel": "Avbryt", "Nitrox_CommandNotAvailable": "Denne kommandoen er ikke tilgjengelig i Nitrox", "Nitrox_ConnectTo": "Koble til", + "Nitrox_DenyOwnershipHand": "En annen spiller samhandler med det objektet", "Nitrox_DisconnectedSession": "Frakoblet fra tjener", "Nitrox_DiscordAccept": "Godta", "Nitrox_DiscordDecline": "Avslå", + "Nitrox_DiscordInGame": "Spiller som {PLAYER}", + "Nitrox_DiscordInGameState": "Dykk ned i dypet", + "Nitrox_DiscordMainMenuState": "Lurker i menyen", + "Nitrox_DiscordMultiplayerMenu": "Trykk på Flerspiller i hovedmenyen hvis du vil bli med i et spill med andre", "Nitrox_DiscordPressToFocus": "Trykk for å låse opp", "Nitrox_DiscordRequestText": "Forespurte deltagelse i din økt", "Nitrox_EnterName": "Skriv inn spillernavnet ditt", + "Nitrox_ErrorDesyncDetected": "[Sikker bygning] Denne basen er for øyeblikket desynkronisert, så du kan ikke endre den med mindre du synkroniserer bygninger på nytt (i Nitrox-innstillingene)", + "Nitrox_ErrorRecentBuildUpdate": "Kan ikke endre en base som nylig ble oppdatert av en annen spiller", + "Nitrox_Failure": "En feil har oppstått", + "Nitrox_FinishedResyncRequest": "Det tok {TIME} ms å synkronisere {COUNT} enheter på nytt", "Nitrox_FirewallInterfering": "Der ser ut til at brannmursinnstillingene ikke går overens", "Nitrox_HideIp": "Skjul IP-adresser", + "Nitrox_HidePing": "Skjul ping", + "Nitrox_IntroUWEPresents": "UNKNOWN WORLDS ENTERTAINMENT\n&\nNITROX-TEAMET\n\nPRESENTERER", + "Nitrox_IntroWaitingPartner": "Venter på at en partner skal bli med\n\nTrykk på {0} for å hoppe over ventetiden", "Nitrox_InvalidUserName": "Skriv inn et gyldig spillernavn.\n\nDet kan ikke inneholde mellomrom eller tvilsomme tegn\nTillatte tegn: A-Z a-z 0-9 _ . -\nLengde: [3, 25]", - "Nitrox_Join": "Ta del", - "Nitrox_JoinServerFailed": "Kunne ikke ta del i tjener", - "Nitrox_JoinServerIpAddress": "Tjener-IP", + "Nitrox_Join": "Bli med", "Nitrox_JoinServerPassword": "Passord:", "Nitrox_JoinServerPasswordHeader": "Tjenerpassord kreves", - "Nitrox_JoiningSession": "Tar del i flerspiller-økt", + "Nitrox_JoiningSession": "Blir med i flerspiller-økt", + "Nitrox_Kick": "Kast ut {PLAYER}", + "Nitrox_KickQuestion": "Kast ut {PLAYER}?", "Nitrox_LaunchGame": "Starter spill …", - "Nitrox_LoadingScreenWarn": "Forvent krasj i spillet som følge av feil", + "Nitrox_LoadingScreenWarn": "Forvent spill-ødeleggende bugs", "Nitrox_LostConnection": "Mistet tilkoblingen til spilltjeneren", "Nitrox_LostConnectionWarn": "Ikke lenger tilkoblet tjeneren", "Nitrox_Multiplayer": "Flerspiller", "Nitrox_MultiplayerLoaded": "Flerspillerklient innlastet …", - "Nitrox_PlayerColor": "Spillerfarge", - "Nitrox_PlayerKicked": "Du har blitt utkastet fra tjeneren", + "Nitrox_Mute": "Demp {PLAYER}", + "Nitrox_MuteQuestion": "Demp {PLAYER}?", + "Nitrox_MutedPlayer": "Dempet {PLAYER}", + "Nitrox_OutOfDateClient": "Din Nitrox installasjon er utdatert. Server: {serverVersion}, Yours: {localVersion}.", + "Nitrox_OutOfDateServer": "Tjeneren kjører på en eldre versjon av Nitrox. Be Admin oppgradere eller nedgradere din Nitrox installasjon. Server: {serverVersion}, Yours: {localVersion}.", + "Nitrox_PlayerDied": "{PLAYER} døde", + "Nitrox_PlayerDisconnected": "{PLAYER} forlot", + "Nitrox_PlayerJoined": "{PLAYER} ble med i spillet.", + "Nitrox_PlayerKicked": "Du har blitt kastet ut fra tjeneren", + "Nitrox_PlayerLeft": "{PLAYER} forlot spillet.", + "Nitrox_PlayerListTabName": "Spillerliste", "Nitrox_RejectedSessionPolicy": "Reservasjon avslått …", + "Nitrox_RemotePlayerObstacle": "En annen spiller er enten inne i, eller for nære målet for dekonstruksjon.", "Nitrox_RequestingSessionPolicy": "Forespør øktpraksis-info …", + "Nitrox_ResyncBuildings": "Synkroniser basebygninger på nytt", + "Nitrox_ResyncOnCooldown": "Du må vente {TIME_LEFT} sekunder for å sende en ny forespørsel om synkronisering", + "Nitrox_ResyncRequested": "Utstedte en resynkroniseringsforespørsel for baser", + "Nitrox_ResyncSettings": "Resynkronisering", + "Nitrox_SafeBuilding": "Trygg bygning", + "Nitrox_SafeBuildingLog": "Sikker byggelogg", "Nitrox_ServerStopped": "Tjeneren stoppet", - "Nitrox_SilenceChat": "Forstum sludring", - "Nitrox_SilencedChatNotif": "Sludringen er nå forstummet", + "Nitrox_ShowPing": "Vis ping", + "Nitrox_SilenceChat": "Demp chat", + "Nitrox_SilencedChatNotif": "Chatten er nå dempet", "Nitrox_StartServer": "Start tjeneren din først for å ta del i din selvtjente verden", "Nitrox_StreamerSettings": "Strømmingsmodus", - "Nitrox_SubmitPassword": "Send inn", "Nitrox_SyncingWorld": "Synkroniserer flerspillerverden …", - "Nitrox_UnableToConnect": "Kunne ikke koble til fjerntjeneren på:", - "Nitrox_Waiting": "Venter på å bli med i køen …", + "Nitrox_TeleportTo": "Teleporter til {PLAYER}", + "Nitrox_TeleportToMe": "Teleporter {PLAYER} til meg", + "Nitrox_TeleportToMeQuestion": "Teleportere {PLAYER} til meg?", + "Nitrox_TeleportToQuestion": "Teleportere til {PLAYER}?", + "Nitrox_ThankForPlaying": "Takk for at du bruker Nitrox!", + "Nitrox_UnableToConnect": "Kunne ikke koble til tjeneren på:", + "Nitrox_Unmute": "Slå på lyd fra {PLAYER}", + "Nitrox_UnmuteQuestion": "Slå på lyd fra {PLAYER}?", + "Nitrox_UnmutedPlayer": "Slo på lyd fra {PLAYER}", + "Nitrox_Waiting": "Venter i spillerkøen …", "Nitrox_WaitingPassword": "Venter på at tjenerpassordet skrives inn …", - "Nitrox_WaitingUserInput": "Venter på brukerinndata …" + "Nitrox_WaitingUserInput": "Venter på brukerinndata …", + "Nitrox_WorldSettling": "Venter på at verden skal koble seg sammen…" } diff --git a/Nitrox.Assets.Subnautica/LanguageFiles/pl.json b/Nitrox.Assets.Subnautica/LanguageFiles/pl.json index 58cabcf87b..c9557e60de 100644 --- a/Nitrox.Assets.Subnautica/LanguageFiles/pl.json +++ b/Nitrox.Assets.Subnautica/LanguageFiles/pl.json @@ -1,56 +1,86 @@ { "Nitrox_AddServer": "Dodaj serwer", - "Nitrox_AddServerAdd": "Dodaj", - "Nitrox_AddServerHost": "Adres:", - "Nitrox_AddServerName": "Nazwa:", - "Nitrox_AddServerPort": "Port:", + "Nitrox_BuildingDesyncDetected": "Serwer wykrył desynchronizacje względem budynków lokalnego klienta (idź do ustawień Nitrox aby wysłać prośbę o ponowną synchronizacje )", + "Nitrox_BuildingSettings": "Budowanie Bazy", "Nitrox_Cancel": "Anuluj", - "Nitrox_CommandNotAvailable": "Ta komenda jest niedostępna w Nitrox", + "Nitrox_CommandNotAvailable": "Ta komenda nie jest dostępna w Nitrox", + "Nitrox_Confirm": "Potwierdź", "Nitrox_ConnectTo": "Połącz z", + "Nitrox_DenyOwnershipHand": "Inny gracz jest w interakcji z tym obiektem", "Nitrox_DisconnectedSession": "Odłączono od serwera", "Nitrox_DiscordAccept": "Akceptuj", "Nitrox_DiscordDecline": "Odrzuć", - "Nitrox_DiscordInGame": "Granie jako {PLAYER}", - "Nitrox_DiscordPressToFocus": "Kliknij aby odblokować", + "Nitrox_DiscordInGame": "Gra jako {PLAYER}", + "Nitrox_DiscordInGameState": "Pośród odchłani", + "Nitrox_DiscordMainMenuState": "Czai się w menu", + "Nitrox_DiscordMultiplayerMenu": "Aby dołączyć do sesji należy nacisnąć przycisk Multiplayer w menu głównym", + "Nitrox_DiscordPressToFocus": "Naciśnij aby odblokować", "Nitrox_DiscordRequestText": "Poprosił o dołączenie do twojej sesji", - "Nitrox_EnterName": "Wpisz swoją nazwę gracza", - "Nitrox_FirewallInterfering": "Wygląda na to, że zapora sieciowa blokuje połączenie", + "Nitrox_EnterName": "Wpisz swoją nazwę", + "Nitrox_ErrorDesyncDetected": "[Bezpieczne Budowanie] Ta baza jest aktualnie zdesynchronizowana więc nie możesz jej edytować, chyba że ponownie zsynchronizujesz budynki (w ustawieniach Nitrox)", + "Nitrox_ErrorRecentBuildUpdate": "Nie można edytować bazy, która niedawno była zaktualizowana przez innego gracza", + "Nitrox_Failure": "Wystąpił błąd", + "Nitrox_FinishedResyncRequest": "Ponowna synchronizacja {COUNT} elementów trwała {TIME}ms", + "Nitrox_FirewallInterfering": "Wygląda na to, że twoja zapora sieciowa blokuje połączenie", "Nitrox_HideIp": "Ukryj adresy IP", "Nitrox_HidePing": "Ukryj Ping", - "Nitrox_InvalidUserName": "Wpisz poprawną nazwę gracza!\n\nNie może zawierać żadnych spacji ani niepewnych znaków\nDozwolone znaki: A-Z a-z 0-9 _ . -\nDługość: [3, 25]", + "Nitrox_IntroUWEPresents": "UNKNOWN WORLDS ENTERTAINMENT\n&\nTHE NITROX-TEAM\n\nPREZENTUJĄ", + "Nitrox_IntroWaitingPartner": "Oczekiwanie na dołączenie partnera\n\nNaciśnij {0}, aby pominąć oczekiwanie", + "Nitrox_InvalidUserName": "Proszę wpisać poprawną nazwę gracza.\n\nNie może zawierać żadnych spacji ani niedozwolonych znaków\nDozwolone znaki: A-Z a-z 0-9 _ . -\nDługość: [3, 25]", "Nitrox_Join": "Dołącz", - "Nitrox_JoinServerFailed": "Nie można połączyć się z serwerem", - "Nitrox_JoinServerIpAddress": "IP serwera", + "Nitrox_JoinServer": "Dołączanie:", "Nitrox_JoinServerPassword": "Hasło:", "Nitrox_JoinServerPasswordHeader": "Serwer wymaga hasła", + "Nitrox_JoinServerPlaceholder": "Proszę podać hasło serwera", "Nitrox_JoiningSession": "Dołączanie do sesji wieloosobowej", + "Nitrox_Kick": "Wyrzuć {PLAYER}", "Nitrox_KickQuestion": "Wyrzucić {PLAYER}?", "Nitrox_LaunchGame": "Uruchamianie gry…", - "Nitrox_LoadingScreenWarn": "Spodziewaj się błędów utrudniających rozgrywkę", - "Nitrox_LostConnection": "Utracono połączenie z serwerem gry", - "Nitrox_LostConnectionWarn": "Brak połączenia z serwerem", + "Nitrox_LoadingScreenWarn": "Spodziewaj się poważnych błędów", + "Nitrox_LostConnection": "Utracono połączenie z serwerem", + "Nitrox_LostConnectionWarn": "Połączenie z serwerem utracone", + "Nitrox_MissingPermission": "Nie masz uprawnień do wykonania tego polecenia [{PERMISSION}]", "Nitrox_Multiplayer": "Gra wieloosobowa", "Nitrox_MultiplayerLoaded": "Klient wieloosobowy wczytany…", + "Nitrox_Mute": "Wycisz {PLAYER}", "Nitrox_MuteQuestion": "Wyciszyć {PLAYER}?", "Nitrox_MutedPlayer": "Wyciszono {PLAYER}", - "Nitrox_PlayerColor": "Kolor gracza", - "Nitrox_PlayerKicked": "Wyrzucono Cię z serwera", + "Nitrox_OK": "Ok", + "Nitrox_OutOfDateClient": "Zainstalowana wersja Nitrox jest przestarzała. Wersja Serwera: {serverVersion}, Twoja Wersja: {localVersion}.", + "Nitrox_OutOfDateServer": "Serwer działa na przestarzałej wersji Nitrox. Poproś administratora serwera o aktualizacje, bądź instalacje wcześniejszej wersji Nitrox. Wersja Serwera: {serverVersion}, Twoja Wersja: {localVersion}.", + "Nitrox_PlayerDied": "{PLAYER} umiera", + "Nitrox_PlayerDisconnected": "{PLAYER} rozłączył/a się", + "Nitrox_PlayerJoined": "{PLAYER} dołączył/a do gry.", + "Nitrox_PlayerKicked": "Zostałeś wyrzucony z serwera", + "Nitrox_PlayerLeft": "{PLAYER} wyszedł/a z gry.", "Nitrox_PlayerListTabName": "Lista Graczy", "Nitrox_RejectedSessionPolicy": "Rezerwacja odrzucona…", - "Nitrox_RequestingSessionPolicy": "Żądanie informacji o warunkach sesji…", - "Nitrox_ServerStopped": "Serwer zatrzymany", + "Nitrox_RemotePlayerObstacle": "Inny gracz jest wewnątrz lub blisko demontowalnego celu.", + "Nitrox_RequestingSessionPolicy": "Uzyskiwanie informacji o warunkach sesji…", + "Nitrox_ResyncBuildings": "Ponownie zsynchronizuj budynki bazowe", + "Nitrox_ResyncOnCooldown": "Musisz poczekać {TIME_LEFT} sekund, aby wysłać kolejną prośbę o ponowną synchronizację", + "Nitrox_ResyncRequested": "Wysłano żądanie ponownej synchronizacji baz", + "Nitrox_ResyncSettings": "Resynchronizacja", + "Nitrox_SafeBuilding": "Bezpieczne budowanie", + "Nitrox_SafeBuildingLog": "Log bezpiecznego budowania", + "Nitrox_ServerStopped": "Serwer został zatrzymany", "Nitrox_ShowPing": "Pokaż Ping", "Nitrox_SilenceChat": "Wycisz czat", "Nitrox_SilencedChatNotif": "Czat jest teraz wyciszony", - "Nitrox_StartServer": "Najpierw uruchom serwer aby dołączyć do swojego świata", + "Nitrox_StartServer": "Aby używać własnego świata, musisz najpierw uruchomić serwer", "Nitrox_StreamerSettings": "Tryb Streamera", - "Nitrox_SubmitPassword": "Potwierdź", - "Nitrox_SyncingWorld": "Synchronizacja świata…", - "Nitrox_UnableToConnect": "Nie można połączyć się ze zdalnym serwerem:", - "Nitrox_UnmuteQuestion": "Odciszyć {PLAYER}?", - "Nitrox_UnmutedPlayer": "Odciszono {PLAYER}", + "Nitrox_SyncingWorld": "Synchronizowanie świata…", + "Nitrox_TeleportTo": "Teleportuj się do {PLAYER}", + "Nitrox_TeleportToMe": "Teleportuj {PLAYER} do siebie", + "Nitrox_TeleportToMeQuestion": "Przeteleportować {PLAYER} do siebie?", + "Nitrox_TeleportToQuestion": "Przeteleportować do {PLAYER}?", + "Nitrox_ThankForPlaying": "Dziękujemy za korzystanie z Nitrox!", + "Nitrox_UnableToConnect": "Nie można połączyć się z serwerem pod adresem:", + "Nitrox_Unmute": "Wyłącz wyciszenie {PLAYER}", + "Nitrox_UnmuteQuestion": "Wyłączyć wyciszenie {PLAYER}?", + "Nitrox_UnmutedPlayer": "{PLAYER} już nie jest wyciszony", "Nitrox_Waiting": "Oczekiwanie w kolejce do dołączenia…", "Nitrox_WaitingPassword": "Oczekiwanie na wprowadzenie hasła do serwera…", - "Nitrox_WaitingUserInput": "Oczekiwanie na dane od użytkownika…", - "Nitrox_WorldSettling": "Oczekiwanie na osadzenie świata…" + "Nitrox_WaitingUserInput": "Oczekiwanie na dane użytkownika…", + "Nitrox_WorldSettling": "Oczekiwanie na Osadzenie Świata…" } diff --git a/Nitrox.Assets.Subnautica/LanguageFiles/pt-BR.json b/Nitrox.Assets.Subnautica/LanguageFiles/pt-BR.json index 0d27645ea7..e56e88033d 100644 --- a/Nitrox.Assets.Subnautica/LanguageFiles/pt-BR.json +++ b/Nitrox.Assets.Subnautica/LanguageFiles/pt-BR.json @@ -1,32 +1,37 @@ { "Nitrox_AddServer": "Adicionar Servidor", - "Nitrox_AddServerAdd": "Adicionar", - "Nitrox_AddServerHost": "IP:", - "Nitrox_AddServerName": "Nome:", - "Nitrox_AddServerPort": "Porta:", + "Nitrox_BuildingDesyncDetected": "O servidor detectou uma dessincronização com as construções do cliente local (vá para as configurações do Nitrox para solicitar uma ressincronização)", + "Nitrox_BuildingSettings": "Construção de base", "Nitrox_Cancel": "Cancelar", "Nitrox_CommandNotAvailable": "Este comando não está disponível no Nitrox", + "Nitrox_Confirm": "Confirmar", "Nitrox_ConnectTo": "Conectar a", + "Nitrox_DenyOwnershipHand": "Outro jogador está interagindo com esse objeto", "Nitrox_DisconnectedSession": "Desconectado do servidor", "Nitrox_DiscordAccept": "Aceitar", "Nitrox_DiscordDecline": "Rejeitar", "Nitrox_DiscordInGame": "Jogando como {PLAYER}", "Nitrox_DiscordInGameState": "Mergulhando no abismo", - "Nitrox_DiscordMainMenuState": "Navegando ao menu", + "Nitrox_DiscordMainMenuState": "Navegando pelo menu", "Nitrox_DiscordMultiplayerMenu": "Por favor selecione o botão multijogador no menu principal caso queira se juntar à sessão", "Nitrox_DiscordPressToFocus": "Pressione para desbloquear", "Nitrox_DiscordRequestText": "Solicitou para entrar na sua sessão atual", "Nitrox_EnterName": "Nome do jogador", + "Nitrox_ErrorDesyncDetected": "[Construção Segura] Esta base está atualmente dessincronizada, então você não pode modificá-la, a menos que sincronize novamente as construções (nas configurações do Nitrox)", + "Nitrox_ErrorRecentBuildUpdate": "Não é possível modificar uma base que foi atualizada recentemente por outro jogador", "Nitrox_Failure": "Um erro ocorreu", + "Nitrox_FinishedResyncRequest": "Demorou {TIME}ms para ressincronizar {COUNT} entities", "Nitrox_FirewallInterfering": "As configurações do seu Firewall estão em conflito", "Nitrox_HideIp": "Ocultar IP", "Nitrox_HidePing": "Ocultar Ping", + "Nitrox_IntroUWEPresents": "UNKNOWN WORLDS ENTERTAINMENT\n&\nTHE NITROX-TEAM\n\nAPRESENTA", + "Nitrox_IntroWaitingPartner": "Aguardando a entrada de um parceiro\n\nPressione {0} para pular a espera", "Nitrox_InvalidUserName": "Por favor, entre com um nome válido\n\nNão pode conter espaços ou caracteres inválidos\nSão aceitos: A-Z a-z 0-9.\nEntre [3 caracteres até 25]", "Nitrox_Join": "Entrar", - "Nitrox_JoinServerFailed": "Não foi possível entrar no servidor", - "Nitrox_JoinServerIpAddress": "IP do Servidor", + "Nitrox_JoinServer": "Entrando:", "Nitrox_JoinServerPassword": "Senha:", "Nitrox_JoinServerPasswordHeader": "O Servidor selecionado necessita de senha", + "Nitrox_JoinServerPlaceholder": "Por favor insira a senha do servidor", "Nitrox_JoiningSession": "Entrando na Sessão", "Nitrox_Kick": "Expulsar {PLAYER}", "Nitrox_KickQuestion": "Expulsar {PLAYER}?", @@ -34,33 +39,46 @@ "Nitrox_LoadingScreenWarn": "Expectável bugs que quebram o jogo", "Nitrox_LostConnection": "Conexão perdida com o servidor do jogo", "Nitrox_LostConnectionWarn": "Não está mais conectado ao servidor", + "Nitrox_MissingPermission": "Você não tem permissão para executar este comando [{PERMISSION}]", "Nitrox_Multiplayer": "Multijogador", "Nitrox_MultiplayerLoaded": "Cliente multijogador carregado…", "Nitrox_Mute": "Mutar {PLAYER}", "Nitrox_MuteQuestion": "Mutar {PLAYER}?", "Nitrox_MutedPlayer": "Mutou {PLAYER}", - "Nitrox_PlayerColor": "Cor do jogador", + "Nitrox_OK": "Ok", + "Nitrox_OutOfDateClient": "A sua instalação do Nitrox está desatualizada. Servidor: {serverVersion}, Sua: {localVersion}.", + "Nitrox_OutOfDateServer": "O servidor está rodando em uma versão antiga do Nitrox. Peça para o administrador do servidor para atualizar ou desatualizar a sua instalação do Nitrox. Versão do Servidor: {serverVersion}, Sua Versão: {localVersion}.", + "Nitrox_PlayerDied": "{PLAYER} morreu", + "Nitrox_PlayerDisconnected": "{PLAYER} desconectou-se", + "Nitrox_PlayerJoined": "{PLAYER} entrou no jogo.", "Nitrox_PlayerKicked": "Você foi expulso do servidor", + "Nitrox_PlayerLeft": "{PLAYER} saiu do jogo.", "Nitrox_PlayerListTabName": "Lista de jogadores", "Nitrox_RejectedSessionPolicy": "Reserva rejeitada…", + "Nitrox_RemotePlayerObstacle": "Outro jogador ou está dentro ou muito próximo do alvo desconstruível.", "Nitrox_RequestingSessionPolicy": "Solicitando informações da sessão…", + "Nitrox_ResyncBuildings": "Ressincronizar construções de bases", + "Nitrox_ResyncOnCooldown": "Você precisa esperar {TIME_LEFT} segundos para poder enviar uma solicitação de ressincronização", + "Nitrox_ResyncRequested": "Realizou uma solicitação de ressincronização para bases", + "Nitrox_ResyncSettings": "Ressincronização", + "Nitrox_SafeBuilding": "Construção segura", + "Nitrox_SafeBuildingLog": "Registro de construção segura", "Nitrox_ServerStopped": "O servidor foi fechado", "Nitrox_ShowPing": "Mostrar ping", "Nitrox_SilenceChat": "Silenciar a conversa", "Nitrox_SilencedChatNotif": "O chat agora está silenciado", "Nitrox_StartServer": "Inicie seu servidor primeiro para entrar na sua sessão", "Nitrox_StreamerSettings": "Modo Streamer", - "Nitrox_SubmitPassword": "Entrar", "Nitrox_SyncingWorld": "Sincronizando com Servidor Multiplayer…", - "Nitrox_TeleportTo": "Teletransporte para {PLAYER}", - "Nitrox_TeleportToMe": "Teleporte {PLAYER} para mim", - "Nitrox_TeleportToMeQuestion": "Teleportar {PLAYER} para mim?", - "Nitrox_TeleportToQuestion": "Teleportar para {PLAYER}?", + "Nitrox_TeleportTo": "Teletransportar para {PLAYER}", + "Nitrox_TeleportToMe": "Teletransportar {PLAYER} para mim", + "Nitrox_TeleportToMeQuestion": "Teletransportar {PLAYER} para mim?", + "Nitrox_TeleportToQuestion": "Teletransportar para {PLAYER}?", "Nitrox_ThankForPlaying": "Obrigado por utilizar Nitrox !", "Nitrox_UnableToConnect": "Não foi possível conectar com o Servidor remoto:", "Nitrox_Unmute": "Desmutar {PLAYER}", "Nitrox_UnmuteQuestion": "Desmutar {PLAYER}?", - "Nitrox_UnmutedPlayer": "Desmutado {PLAYER}", + "Nitrox_UnmutedPlayer": "{PLAYER} desmutado", "Nitrox_Waiting": "Aguardando na fila de entrada…", "Nitrox_WaitingPassword": "Aguardando senha do servidor…", "Nitrox_WaitingUserInput": "Aguardando informações do usuário…", diff --git a/Nitrox.Assets.Subnautica/LanguageFiles/pt.json b/Nitrox.Assets.Subnautica/LanguageFiles/pt.json index 75158fb842..c906dfb206 100644 --- a/Nitrox.Assets.Subnautica/LanguageFiles/pt.json +++ b/Nitrox.Assets.Subnautica/LanguageFiles/pt.json @@ -1,56 +1,74 @@ { "Nitrox_AddServer": "Adicionar Servidor", - "Nitrox_AddServerAdd": "Adicionar", - "Nitrox_AddServerHost": "IP:", - "Nitrox_AddServerName": "Nome:", - "Nitrox_AddServerPort": "Porta:", + "Nitrox_BuildingDesyncDetected": "O servidor detetou uma dessincronização com os edifícios locais do cliente (vá para as definições do Nitrox para solicitar uma ressincronização)", + "Nitrox_BuildingSettings": "Construção de base", "Nitrox_Cancel": "Cancelar", "Nitrox_CommandNotAvailable": "Este comando não está disponível no Nitrox", + "Nitrox_Confirm": "Confirmar", "Nitrox_ConnectTo": "Conectar a", + "Nitrox_DenyOwnershipHand": "Outro jogador está interagindo com esse objeto", "Nitrox_DisconnectedSession": "Desconectado do servidor", "Nitrox_DiscordAccept": "Aceitar", "Nitrox_DiscordDecline": "Rejeitar", "Nitrox_DiscordInGame": "Jogando como {PLAYER}", "Nitrox_DiscordInGameState": "Mergulhando no abismo", - "Nitrox_DiscordMainMenuState": "À espreita no menu", + "Nitrox_DiscordMainMenuState": "Espreitando no menu", "Nitrox_DiscordMultiplayerMenu": "Por favor pressione no botão Multiplayer no menu principal se quiser participar numa sessão", "Nitrox_DiscordPressToFocus": "Pressione para desbloquear", "Nitrox_DiscordRequestText": "Solicitado para se juntar na sua sessão atual", "Nitrox_EnterName": "Introduz o teu nome de jogador", - "Nitrox_Failure": "um erro ocorreu", + "Nitrox_ErrorDesyncDetected": "[Construção Segura] Esta base está atualmente dessincronizada, portanto, você não pode modificá-la a menos que ressincronize os edifícios (nas configurações do Nitrox)", + "Nitrox_ErrorRecentBuildUpdate": "Não é possível modificar uma base que foi atualizada recentemente por outro jogador", + "Nitrox_Failure": "Ocorreu um erro", + "Nitrox_FinishedResyncRequest": "Levou {TIME}ms para ressincronizar {COUNT} entidades", "Nitrox_FirewallInterfering": "Parece que as configurações da tua firewall estão interferindo", "Nitrox_HideIp": "Ocultar endereços IP", "Nitrox_HidePing": "Ocultar Marcação", - "Nitrox_InvalidUserName": "Por favor introduz um nome de jogador válido.\n\nNão pode conter nenhum espaço ou caracteres duvidosos\nCaracteres permitidos: A-Z a-z 0-9 _ . -\nComprimento: [3, 25]", + "Nitrox_IntroUWEPresents": "UNKNOWN WORLDS ENTRETENIMENTO\n&\nO TIME-NITROX\n\nAPRESENTAM", + "Nitrox_IntroWaitingPartner": "Aguardando um parceiro entrar\n\nPressione {0} para pular espera", + "Nitrox_InvalidUserName": "Por favor insira um nome de jogador válido.\n\nNão pode conter nenhum espaço ou caracteres duvidosos\nCaracteres permitidos: A-Z a-z 0-9 _ . -\nComprimento: [3, 25]", "Nitrox_Join": "Entrar", - "Nitrox_JoinServerFailed": "Não foi possível entrar no servidor", - "Nitrox_JoinServerIpAddress": "IP do servidor", + "Nitrox_JoinServer": "Entrando:", "Nitrox_JoinServerPassword": "Senha:", "Nitrox_JoinServerPasswordHeader": "O Servidor selecionado necessita senha", - "Nitrox_JoiningSession": "Entrando na Sessão", - "Nitrox_Kick": "Remover {PLAYER}", - "Nitrox_KickQuestion": "Remover {PLAYER}?", + "Nitrox_JoinServerPlaceholder": "Por favor, insira a senha do servidor", + "Nitrox_JoiningSession": "Entrando na sessão multijogador", + "Nitrox_Kick": "Expulsar {PLAYER}", + "Nitrox_KickQuestion": "Expulsar {PLAYER}?", "Nitrox_LaunchGame": "Iniciando jogo…", - "Nitrox_LoadingScreenWarn": "Expectável bugs que quebram o jogo", - "Nitrox_LostConnection": "Conexão perdida com o servidor do jogo", + "Nitrox_LoadingScreenWarn": "É esperado que haja bugs que quebrem o jogo", + "Nitrox_LostConnection": "Conexão perdida com o servidor de jogo", "Nitrox_LostConnectionWarn": "Não está mais conectado ao servidor", + "Nitrox_MissingPermission": "Você não tem permissão para executar este comando [{PERMISSION}]", "Nitrox_Multiplayer": "Multijogador", "Nitrox_MultiplayerLoaded": "Cliente multijogador carregado…", "Nitrox_Mute": "Silenciar {PLAYER}", "Nitrox_MuteQuestion": "Silenciar {PLAYER}?", "Nitrox_MutedPlayer": "{PLAYER} silenciado", - "Nitrox_PlayerColor": "Cor do jogador", + "Nitrox_OK": "Ok", + "Nitrox_OutOfDateClient": "Sua instalação Nitrox está desatualizada. Servidor: {serverVersion}, Sua Instalação: {localVersion}.", + "Nitrox_OutOfDateServer": "O servidor está rodando uma versão mais antiga do Nitrox. Peça ao administrador do servidor para atualizar o servidor ou faça uma versão mais antiga da sua instalação do Nitrox. Servidor: {serverVersion}, Sua: {localVersion}.", + "Nitrox_PlayerDied": "{PLAYER} morreu", + "Nitrox_PlayerDisconnected": "{PLAYER} desconectou-se", + "Nitrox_PlayerJoined": "{PLAYER} entrou no jogo.", "Nitrox_PlayerKicked": "Você foi expulso do servidor", + "Nitrox_PlayerLeft": "{PLAYER} saiu do jogo.", "Nitrox_PlayerListTabName": "Lista de Jogadores", "Nitrox_RejectedSessionPolicy": "Reserva rejeitada…", + "Nitrox_RemotePlayerObstacle": "Outro jogador está dentro ou muito próximo do alvo desconstrúivel.", "Nitrox_RequestingSessionPolicy": "Solicitando informações de política de sessão…", + "Nitrox_ResyncBuildings": "Ressincronizar edifícios", + "Nitrox_ResyncOnCooldown": "Precisa esperar {TIME_LEFT} segundos para poder enviar um pedido de ressincronização", + "Nitrox_ResyncRequested": "Emitida um pedido de ressincronização para bases", + "Nitrox_ResyncSettings": "Ressincronização", + "Nitrox_SafeBuilding": "Construção segura", + "Nitrox_SafeBuildingLog": "Registo da construção segura", "Nitrox_ServerStopped": "O servidor foi fechado", "Nitrox_ShowPing": "Mostrar marcação", "Nitrox_SilenceChat": "Silenciar a conversa", "Nitrox_SilencedChatNotif": "A conversa está agora silenciada", "Nitrox_StartServer": "Inicia primeiro o teu servidor para te juntares ao teu próprio mundo", "Nitrox_StreamerSettings": "Modo streamer", - "Nitrox_SubmitPassword": "Submeter", "Nitrox_SyncingWorld": "Sincronizando mundo multijogador…", "Nitrox_TeleportTo": "Teleportar para {PLAYER}", "Nitrox_TeleportToMe": "Teleportar {PLAYER} para mim", diff --git a/Nitrox.Assets.Subnautica/LanguageFiles/ro.json b/Nitrox.Assets.Subnautica/LanguageFiles/ro.json index 4eb45c5af9..5b2becfa42 100644 --- a/Nitrox.Assets.Subnautica/LanguageFiles/ro.json +++ b/Nitrox.Assets.Subnautica/LanguageFiles/ro.json @@ -1,48 +1,48 @@ { "Nitrox_AddServer": "Adaugă server", - "Nitrox_AddServerAdd": "Adăugă", - "Nitrox_AddServerHost": "Gazdă:", - "Nitrox_AddServerName": "Nume:", - "Nitrox_AddServerPort": "Port:", "Nitrox_Cancel": "Anulare", "Nitrox_CommandNotAvailable": "Acestă comandă nu este disponibilă în Nitrox", - "Nitrox_ConnectTo": "Conectează la", + "Nitrox_ConnectTo": "Conectează-te la", "Nitrox_DisconnectedSession": "Deconectat de la server", "Nitrox_DiscordAccept": "Acceptă", "Nitrox_DiscordDecline": "Respinge", - "Nitrox_DiscordInGame": "Jucănd ca {PLAYER}", - "Nitrox_DiscordInGameState": "Scufundă în abis", - "Nitrox_DiscordMainMenuState": "Păndind în meniu", + "Nitrox_DiscordInGame": "Jucând ca {PLAYER}", + "Nitrox_DiscordInGameState": "Se scufundă în abis", + "Nitrox_DiscordMainMenuState": "Stând în meniu", "Nitrox_DiscordMultiplayerMenu": "Vă rugăm să apăsați pe butonul Multiplayer din meniul principal dacă doriți să vă alăturați unei sesiuni", - "Nitrox_DiscordPressToFocus": "Apasă ca să deblochezi", - "Nitrox_DiscordRequestText": "S-a solicitat să se alăture sesiunii dvs", + "Nitrox_DiscordPressToFocus": "Apasă pentru a debloca", + "Nitrox_DiscordRequestText": "A solicitat să se alăture sesiunii dvs", "Nitrox_EnterName": "Introduceți numele jucătorului dvs", - "Nitrox_Failure": "O Eroare a avut loc", + "Nitrox_Failure": "A avut loc o eroare", "Nitrox_FirewallInterfering": "Se pare că setările firewall-ului tău interferează", "Nitrox_HideIp": "Ascundeți adresele IP", "Nitrox_HidePing": "Ascunde Ping", "Nitrox_InvalidUserName": "Te rugăm să introduci un nume de jucător valid!\n\n Trebuie să nu conțină spațiu sau caractere ambigue\n Caracterele permise : A-Z a-z 0-9 _ . -\nLungime : [3, 25]", - "Nitrox_Join": "Alătură-te", - "Nitrox_JoinServerFailed": "Nu te poți alătura serverului", - "Nitrox_JoinServerIpAddress": "Adresa IP a serverului", + "Nitrox_Join": "Intră", "Nitrox_JoinServerPassword": "Parola:", "Nitrox_JoinServerPasswordHeader": "Parola serverului este necesară", - "Nitrox_JoiningSession": "Alăturarea la sesiune Multiplayer", - "Nitrox_Kick": "Dă Afară pe {PLAYER]", - "Nitrox_KickQuestion": "Dă Afară pe {PLAYER}?", + "Nitrox_JoiningSession": "Se conectează la sesiunea Multiplayer", + "Nitrox_Kick": "Dă-l afară pe {PLAYER]", + "Nitrox_KickQuestion": "Îl dai afară pe {PLAYER}?", "Nitrox_LaunchGame": "Se lansează jocul…", "Nitrox_LoadingScreenWarn": "Așteptă-te la bug-uri care pot strica jocul", - "Nitrox_LostConnection": "Conexiune pierdută la serverul jocului", + "Nitrox_LostConnection": "Conexiune pierdută la server", "Nitrox_LostConnectionWarn": "Nu mai sunțeti conectat la Server", "Nitrox_Multiplayer": "Multiplayer", "Nitrox_MultiplayerLoaded": "Clientul Multiplayer încărcat…", - "Nitrox_Mute": "Dezactivează {PLAYER}", - "Nitrox_MuteQuestion": "Dezactivează {PLAYER}?", - "Nitrox_MutedPlayer": "Dezactivează {PLAYER}", - "Nitrox_PlayerColor": "Culoarea jucătorului", + "Nitrox_Mute": "Amuțește {PLAYER}", + "Nitrox_MuteQuestion": "Îl amuțești pe {PLAYER}?", + "Nitrox_MutedPlayer": "{PLAYER} a fost pus pe mut", + "Nitrox_OutOfDateClient": "Versiunea ta de Nitrox nu este la curent. Server: {serverVersion}, A ta:{localVersion}.", + "Nitrox_OutOfDateServer": "Serverul rulează o versiune mai veche de Nitrox. Cereți administratorului serverului să actualizeze serverul sau să facă un downgrade al instalației tale Nitrox. Server: {serverVersion}, A ta: {localVersion}.", + "Nitrox_PlayerDied": "{PLAYER} a murit", + "Nitrox_PlayerDisconnected": "{PLAYER} a fost deconectat", + "Nitrox_PlayerJoined": "{PLAYER} a intrat în joc.", "Nitrox_PlayerKicked": "Ai fost dat afară de pe server", - "Nitrox_PlayerListTabName": "Listă de Playeri", + "Nitrox_PlayerLeft": "{PLAYER} a ieșit din joc.", + "Nitrox_PlayerListTabName": "Listă de jucători", "Nitrox_RejectedSessionPolicy": "Rezervare respinsă…", + "Nitrox_RemotePlayerObstacle": "Un alt jucător se află fie în interiorul, fie prea aproape de ținta deconstruibilă.", "Nitrox_RequestingSessionPolicy": "Se solicită informații despre politica sesiunii…", "Nitrox_ServerStopped": "Serverul a fost oprit", "Nitrox_ShowPing": "Arată Ping", @@ -50,19 +50,18 @@ "Nitrox_SilencedChatNotif": "Chat-ul este acum dezactivat", "Nitrox_StartServer": "Pornește mai întâi serverul pentru a te alătura lumii găzduite de tine", "Nitrox_StreamerSettings": "Mod Streamer", - "Nitrox_SubmitPassword": "Trimite parola", - "Nitrox_SyncingWorld": "Sincronizarea Lumii Multiplayer…", - "Nitrox_TeleportTo": "Teleportați la {PLAYER}", - "Nitrox_TeleportToMe": "Teleportează {PLAYER} către mine", - "Nitrox_TeleportToMeQuestion": "Teleportează {PLAYER} către mine ?", - "Nitrox_TeleportToQuestion": "Teleportați la {PLAYER}?", - "Nitrox_ThankForPlaying": "Vă mulțumim pentru utilizarea Nitrox!", - "Nitrox_UnableToConnect": "Nu se poate contacta serverul de la distanță la:", - "Nitrox_Unmute": "Activează {PLAYER}", - "Nitrox_UnmuteQuestion": "Activează {PLAYER}?", - "Nitrox_UnmutedPlayer": "Activează {PLAYER}", - "Nitrox_Waiting": "Așteptând în coadă de așteptare pentru a se alătura serverului…", + "Nitrox_SyncingWorld": "Se sincronizează lumea de Multiplayer…", + "Nitrox_TeleportTo": "Teleportează-te la {PLAYER}", + "Nitrox_TeleportToMe": "Teleportează-l pe {PLAYER} către mine", + "Nitrox_TeleportToMeQuestion": "Îl teleportați pe {PLAYER} la dvs ?", + "Nitrox_TeleportToQuestion": "Te teleportezi la {PLAYER}?", + "Nitrox_ThankForPlaying": "Vă mulțumim că utilizați Nitrox!", + "Nitrox_UnableToConnect": "Nu se poate conecta la serverul:", + "Nitrox_Unmute": "Scoate-l de pe mut pe {PLAYER}", + "Nitrox_UnmuteQuestion": "Îl scoți de pe mut pe {PLAYER}?", + "Nitrox_UnmutedPlayer": "{PLAYER} a fost scos de pe mut", + "Nitrox_Waiting": "Ești în coadă pentru a intra pe server…", "Nitrox_WaitingPassword": "Se așteaptă introducerea parolei serverului…", "Nitrox_WaitingUserInput": "Se așteaptă datele introduse de utilizator…", - "Nitrox_WorldSettling": "În așteptarea Stabilirii Lumii…" + "Nitrox_WorldSettling": "În așteptarea stabilirii lumii…" } diff --git a/Nitrox.Assets.Subnautica/LanguageFiles/ru.json b/Nitrox.Assets.Subnautica/LanguageFiles/ru.json index 56e1841a95..364f7b72f3 100644 --- a/Nitrox.Assets.Subnautica/LanguageFiles/ru.json +++ b/Nitrox.Assets.Subnautica/LanguageFiles/ru.json @@ -1,30 +1,32 @@ { "Nitrox_AddServer": "Добавить сервер", - "Nitrox_AddServerAdd": "Добавить", - "Nitrox_AddServerHost": "Адрес:", - "Nitrox_AddServerName": "Имя сервера:", - "Nitrox_AddServerPort": "Порт:", + "Nitrox_BuildingDesyncDetected": "Сервер обнаружил рассинхронизацию со зданиями локального клиента (перейдите в настройки Nitrox, чтобы запросить повторную синхронизацию)", + "Nitrox_BuildingSettings": "Базовое здание", "Nitrox_Cancel": "Отмена", "Nitrox_CommandNotAvailable": "Эта команда недоступна в Nitrox", "Nitrox_ConnectTo": "Подключиться к", + "Nitrox_DenyOwnershipHand": "Другой игрок взаимодействует с этим объектом", "Nitrox_DisconnectedSession": "Отключение от сервера", "Nitrox_DiscordAccept": "Принять", "Nitrox_DiscordDecline": "Отклонить", - "Nitrox_DiscordInGame": "Играть как {PLAYER}", + "Nitrox_DiscordInGame": "Играет как {PLAYER}", "Nitrox_DiscordInGameState": "Погружается в бездну", "Nitrox_DiscordMainMenuState": "Спрятался в меню", "Nitrox_DiscordMultiplayerMenu": "Пожалуйста, нажмите на кнопку «Многопользовательская игра» в главном меню, если вы хотите присоединиться к серверу", "Nitrox_DiscordPressToFocus": "Нажмите чтобы разблокировать", "Nitrox_DiscordRequestText": "Запросил подключение к вашей сессии", "Nitrox_EnterName": "Имя игрока", + "Nitrox_ErrorDesyncDetected": "[Safe Building] Эта база в настоящее время рассинхронизирована, поэтому вы не сможете изменить ее, пока не выполните повторную синхронизацию зданий (в настройках Nitrox)", + "Nitrox_ErrorRecentBuildUpdate": "Невозможно изменить базу, которая была недавно обновлена другим игроком", "Nitrox_Failure": "Произошла ошибка", + "Nitrox_FinishedResyncRequest": "Повторная синхронизация объектов {COUNT} заняла {TIME}ms", "Nitrox_FirewallInterfering": "Некорректные настройки брандмауэра", "Nitrox_HideIp": "Скрыть IP-адреса", "Nitrox_HidePing": "Скрыть Пинг", + "Nitrox_IntroUWEPresents": "UNKNOWN WORLDS ENTERTAINMENT\n&\nКоманда NITROX\n\nпредставляет", + "Nitrox_IntroWaitingPartner": "Ожидание присоединения других игроков\n\nНажмите {0}, чтобы пропустить ожидание", "Nitrox_InvalidUserName": "Пожалуйста введите корректное имя!\n\nОн не может содержать пробелов или сомнительных символов\nДоступные символы: A-Z a-z 0-9 _ . -\nДлинна: [3, 25]", "Nitrox_Join": "Войти", - "Nitrox_JoinServerFailed": "Не удаётся подключится к серверу", - "Nitrox_JoinServerIpAddress": "IP сервера", "Nitrox_JoinServerPassword": "Пароль:", "Nitrox_JoinServerPasswordHeader": "Необходим пароль", "Nitrox_JoiningSession": "Вход в сетевую игру", @@ -39,18 +41,29 @@ "Nitrox_Mute": "Заглушить {PLAYER}", "Nitrox_MuteQuestion": "Заглушить {PLAYER}?", "Nitrox_MutedPlayer": "{PLAYER} заглушен", - "Nitrox_PlayerColor": "Цвет игрока", + "Nitrox_OutOfDateClient": "Установленный Nitrox имеет устаревшую версию. Версия сервера: {serverVersion}, Ваша версия: {localVersion}.", + "Nitrox_OutOfDateServer": "Сервер использует старую версию Nitrox. Попросите администратора сервера обновить версию Nitrox или установите старую версию. Версия сервера: {serverVersion}, Ваша версия: {localVersion}.", + "Nitrox_PlayerDied": "{PLAYER} погиб", + "Nitrox_PlayerDisconnected": "{PLAYER} покинул сервер", + "Nitrox_PlayerJoined": "{PLAYER} присоединился к игре.", "Nitrox_PlayerKicked": "Вы были исключены с сервера", + "Nitrox_PlayerLeft": "{PLAYER} покинул игру.", "Nitrox_PlayerListTabName": "Список игроков", "Nitrox_RejectedSessionPolicy": "Бронирование отклонено…", + "Nitrox_RemotePlayerObstacle": "Другой игрок слишком близко/внутри демонтируемого объекта.", "Nitrox_RequestingSessionPolicy": "Запрос информации о политике сеанса…", + "Nitrox_ResyncBuildings": "Повторная синхронизация базовых зданий", + "Nitrox_ResyncOnCooldown": "Чтобы отправить запрос на повторную синхронизацию, вам нужно подождать {TIME_LEFT} секунд", + "Nitrox_ResyncRequested": "Выполнен запрос на ресинхронизацию баз", + "Nitrox_ResyncSettings": "Ресинхронизация", + "Nitrox_SafeBuilding": "Безопасное строительство", + "Nitrox_SafeBuildingLog": "Журнал безопасного строительства", "Nitrox_ServerStopped": "Сервер был остановлен", "Nitrox_ShowPing": "Показать задержку", "Nitrox_SilenceChat": "Отключить звук в чате", "Nitrox_SilencedChatNotif": "Чат теперь отключен", "Nitrox_StartServer": "Сначала запустите свой сервер, чтобы присоединиться к вашему автономному миру", "Nitrox_StreamerSettings": "Режим стримера", - "Nitrox_SubmitPassword": "Подтвердить", "Nitrox_SyncingWorld": "Синхронизация мира…", "Nitrox_TeleportTo": "Телепортироваться к {PLAYER}", "Nitrox_TeleportToMe": "Телепортировать {PLAYER} ко мне", diff --git a/Nitrox.Assets.Subnautica/LanguageFiles/sk.json b/Nitrox.Assets.Subnautica/LanguageFiles/sk.json index 000d2ae7b8..3ddb9e0dda 100644 --- a/Nitrox.Assets.Subnautica/LanguageFiles/sk.json +++ b/Nitrox.Assets.Subnautica/LanguageFiles/sk.json @@ -1,38 +1,62 @@ { "Nitrox_AddServer": "Pridať server", - "Nitrox_AddServerAdd": "Pridať", - "Nitrox_AddServerHost": "Adresa:", - "Nitrox_AddServerName": "Názov:", - "Nitrox_AddServerPort": "Port:", "Nitrox_Cancel": "Zrušiť", + "Nitrox_CommandNotAvailable": "Tento príkaz nie je dostupný v aplikácii Nitrox", + "Nitrox_Confirm": "Potvrdiť", "Nitrox_ConnectTo": "Pripojiť sa na", "Nitrox_DisconnectedSession": "Odpojený zo serveru", + "Nitrox_DiscordAccept": "Prijať", + "Nitrox_DiscordDecline": "Zamietnuť", + "Nitrox_DiscordInGame": "Hrá ako {PLAYER}", + "Nitrox_DiscordInGameState": "Potápanie sa do priepasti", + "Nitrox_DiscordMainMenuState": "Schováva sa v menu", + "Nitrox_DiscordMultiplayerMenu": "Kliknite na tlačidlo Multiplayer v hlavnom menu, pokiaľ sa chcete pripojiť do hry", + "Nitrox_DiscordPressToFocus": "Kliknite pre odblokovanie", + "Nitrox_DiscordRequestText": "Požiadavka na pripojenie sa do tvojej hry", "Nitrox_EnterName": "Meno hráča", + "Nitrox_Failure": "Vyskytla sa chyba", "Nitrox_FirewallInterfering": "Vyzerá, že vám bránia vaše nastavenia firewallu", "Nitrox_HideIp": "Skryť IP adresy", - "Nitrox_InvalidUserName": "Prosím zadajte platné meno !\n\n Nemôžu v ňom byť medzery ani pochybné znaky.\n Povolené znaky : A-Z a-z 0-9 _ . -\nDĺžka : [3, 25]", + "Nitrox_HidePing": "Schovať Ping", + "Nitrox_InvalidUserName": "Prosím zadajte platné meno !\n\n Nemôžu v ňom byť medzery ani znaky.\n Povolené znaky : A-Z a-z 0-9 _ . -\nDĺžka : [3, 25]", "Nitrox_Join": "Pripojiť sa", - "Nitrox_JoinServerFailed": "Nedá sa pripojiť na server", - "Nitrox_JoinServerIpAddress": "IP adresa servera", "Nitrox_JoinServerPassword": "Heslo:", "Nitrox_JoinServerPasswordHeader": "Server požaduje heslo", "Nitrox_JoiningSession": "Pripájam sa do hry", + "Nitrox_Kick": "Vyhodení {PLAYER}", + "Nitrox_KickQuestion": "Vyhodení {PLAYER}?", "Nitrox_LaunchGame": "Spúštam hru…", "Nitrox_LoadingScreenWarn": "Očakávajte chyby, ktoré kazia hru", - "Nitrox_LostConnection": "Strata pripojenia k serveru", + "Nitrox_LostConnection": "Stráta pripojenia k serveru", + "Nitrox_LostConnectionWarn": "Už nie je pripojený k serveru", "Nitrox_Multiplayer": "Hrať spoločne", "Nitrox_MultiplayerLoaded": "Multiplayer klient načítaný…", - "Nitrox_PlayerColor": "Farba hráča", + "Nitrox_Mute": "Stlmiť {PLAYER}", + "Nitrox_MuteQuestion": "Stlmiť {PLAYER}?", + "Nitrox_MutedPlayer": "Stlmení {PLAYER}", + "Nitrox_PlayerJoined": "{PLAYER} sa pripojil k hre.", "Nitrox_PlayerKicked": "Boli ste vyhodený zo serveru", + "Nitrox_PlayerLeft": "{PLAYER} opustil hru.", + "Nitrox_PlayerListTabName": "List Hráčou", "Nitrox_RejectedSessionPolicy": "Rezervácia odmietnutá…", - "Nitrox_RequestingSessionPolicy": "Pýtam pravidlá relácie…", + "Nitrox_RemotePlayerObstacle": "Iný hráč je buď vo vnútri alebo príliš blízko k dekonštruovateľnému cieľu.", + "Nitrox_RequestingSessionPolicy": "Žiada sa o informácie o policy info…", + "Nitrox_ServerStopped": "Server bol zastavený", + "Nitrox_ShowPing": "Ukázať Ping", "Nitrox_SilenceChat": "Vypnutie chatu", "Nitrox_SilencedChatNotif": "Chat je teraz stlmený", "Nitrox_StartServer": "Najprv spustite server aby ste sa mohli pripojiť do vášho sveta", "Nitrox_StreamerSettings": "Režim streamer", - "Nitrox_SubmitPassword": "Použiť", "Nitrox_SyncingWorld": "Synchronizujem svet…", + "Nitrox_TeleportTo": "Teleportovať sa {PLAYER}", + "Nitrox_TeleportToMe": "Teleportovať {PLAYER} ku mne", + "Nitrox_TeleportToMeQuestion": "Teleportovať {PLAYER} ku mne ?", + "Nitrox_TeleportToQuestion": "Teleportovať sa {PLAYER}?", + "Nitrox_ThankForPlaying": "Ďakujeme za používanie Nitrox!", "Nitrox_UnableToConnect": "Nedá sa kontaktovať server na:", + "Nitrox_Unmute": "Zapnúť zvuk {PLAYER}", + "Nitrox_UnmuteQuestion": "Zapnúť zvuk {PLAYER}?", + "Nitrox_UnmutedPlayer": "Zapnutý Zvuk {PLAYER}", "Nitrox_Waiting": "Čakanie vo fronte pripojení…", "Nitrox_WaitingPassword": "Čakám na zadanie hesla…", "Nitrox_WaitingUserInput": "Čakám na vstup od používateľa…", diff --git a/Nitrox.Assets.Subnautica/LanguageFiles/sl.json b/Nitrox.Assets.Subnautica/LanguageFiles/sl.json index 0967ef424b..bb12d963a4 100644 --- a/Nitrox.Assets.Subnautica/LanguageFiles/sl.json +++ b/Nitrox.Assets.Subnautica/LanguageFiles/sl.json @@ -1 +1,61 @@ -{} +{ + "Nitrox_AddServer": "Dodaj strežnik", + "Nitrox_Cancel": "Prekliči", + "Nitrox_CommandNotAvailable": "Ta ukaz ni na voljo v Nitroxu", + "Nitrox_ConnectTo": "Poveži z", + "Nitrox_DisconnectedSession": "Prekinjena povezava s strežnikom", + "Nitrox_DiscordAccept": "Sprejmi", + "Nitrox_DiscordDecline": "Zavrni", + "Nitrox_DiscordInGame": "Igranje kot {PLAYER}", + "Nitrox_DiscordInGameState": "Potapljanje v brezno", + "Nitrox_DiscordMainMenuState": "Skrivanje v meniju", + "Nitrox_DiscordMultiplayerMenu": "Če se želite pridružiti seji, pritisnite gumb Več igralcev v glavnem meniju", + "Nitrox_DiscordPressToFocus": "Pritisnite za odklepanje", + "Nitrox_DiscordRequestText": "Zaprošen, da se pridruži vaši seji", + "Nitrox_EnterName": "Vnesite svoje ime igralca", + "Nitrox_Failure": "Zgodila se je napaka", + "Nitrox_FirewallInterfering": "Zdi se, da vaše nastavitve požarnega zidu ovirajo", + "Nitrox_HideIp": "Skrivanje naslovov IP", + "Nitrox_HidePing": "Skrij Ping", + "Nitrox_InvalidUserName": "Vnesite veljavno ime igralca.\n\nNe sme vsebovati presledka ali dvomljivih znakov.\nDovoljeni znaki: A-Z a-z 0-9 _ . -\nDolžina: [3, 25]", + "Nitrox_Join": "Pridružite se", + "Nitrox_JoinServerPassword": "Geslo:", + "Nitrox_JoinServerPasswordHeader": "Zahtevano geslo strežnika", + "Nitrox_JoiningSession": "Pridružitev k seji za več igralcev", + "Nitrox_Kick": "Brcanje {PLAYER}", + "Nitrox_KickQuestion": "Brcanje {PLAYER}?", + "Nitrox_LaunchGame": "Zagon igre…", + "Nitrox_LoadingScreenWarn": "Pričakujte hrošče, ki bodo prekinili igro", + "Nitrox_LostConnection": "Izgubljena povezava z igralnim strežnikom", + "Nitrox_LostConnectionWarn": "Ni več povezan s strežnikom", + "Nitrox_Multiplayer": "Večigralstvo", + "Nitrox_MultiplayerLoaded": "Odjemalec za več igralcev je naložen…", + "Nitrox_Mute": "Izklop mikrofona {PLAYER}", + "Nitrox_MuteQuestion": "Izklop mikrofona {PLAYER}?", + "Nitrox_MutedPlayer": "Z utišanjem zvoka {PLAYER}", + "Nitrox_PlayerKicked": "Bili ste izključeni iz strežnika", + "Nitrox_PlayerListTabName": "Seznam igralcev", + "Nitrox_RejectedSessionPolicy": "Rezervacija zavrnjena…", + "Nitrox_RemotePlayerObstacle": "Drug igralec je znotraj cilja, ki ga je mogoče razgraditi, ali pa je preblizu njemu.", + "Nitrox_RequestingSessionPolicy": "Zahtevanje informacij o politiki seje…", + "Nitrox_ServerStopped": "Strežnik je bil ustavljen", + "Nitrox_ShowPing": "Prikaži Ping", + "Nitrox_SilenceChat": "Izklopite klepet", + "Nitrox_SilencedChatNotif": "Klepet je zdaj utišan", + "Nitrox_StartServer": "Najprej zaženite strežnik in se pridružite svojemu samostojno gostovanemu svetu", + "Nitrox_StreamerSettings": "Način streamerja", + "Nitrox_SyncingWorld": "Sinhronizacija sveta za več igralcev…", + "Nitrox_TeleportTo": "Teleport v {PLAYER}", + "Nitrox_TeleportToMe": "Teleportirajte {PLAYER} k meni", + "Nitrox_TeleportToMeQuestion": "Teleportirajte {PLAYER} k meni ?", + "Nitrox_TeleportToQuestion": "Teleport v {PLAYER}?", + "Nitrox_ThankForPlaying": "Hvala za uporabo Nitroxa!", + "Nitrox_UnableToConnect": "Ni mogoče vzpostaviti stika z oddaljenim strežnikom na naslovu:", + "Nitrox_Unmute": "Odklopi izklop mikrofona {PLAYER}", + "Nitrox_UnmuteQuestion": "Odklopi izklop mikrofona {PLAYER}?", + "Nitrox_UnmutedPlayer": "Brez zvoka {PLAYER}", + "Nitrox_Waiting": "Čaka v čakalni vrsti za pridružitev…", + "Nitrox_WaitingPassword": "Čaka na vnos gesla strežnika…", + "Nitrox_WaitingUserInput": "Čakamo na vnos uporabnika…", + "Nitrox_WorldSettling": "V pričakovanju svetovne ureditve…" +} diff --git a/Nitrox.Assets.Subnautica/LanguageFiles/sr-Cyrl.json b/Nitrox.Assets.Subnautica/LanguageFiles/sr-Cyrl.json new file mode 100644 index 0000000000..0967ef424b --- /dev/null +++ b/Nitrox.Assets.Subnautica/LanguageFiles/sr-Cyrl.json @@ -0,0 +1 @@ +{} diff --git a/Nitrox.Assets.Subnautica/LanguageFiles/sr.json b/Nitrox.Assets.Subnautica/LanguageFiles/sr.json index fa0749c8f5..67f8c996e9 100644 --- a/Nitrox.Assets.Subnautica/LanguageFiles/sr.json +++ b/Nitrox.Assets.Subnautica/LanguageFiles/sr.json @@ -1,8 +1,26 @@ { "Nitrox_AddServer": "Dodaj Server", - "Nitrox_AddServerAdd": "Dodaj", - "Nitrox_AddServerHost": "Host:", - "Nitrox_AddServerName": "Ime:", - "Nitrox_AddServerPort": "Port:", - "Nitrox_Cancel": "Poništi" + "Nitrox_BuildingDesyncDetected": "Server je detektovao neslogu sa građevinama lokalnog klijenta (idite u Nitrox podešavanja da zatražite usklađenje)", + "Nitrox_BuildingSettings": "Građenje baza", + "Nitrox_Cancel": "Poništi", + "Nitrox_CommandNotAvailable": "ova komanda nije dostupna u Nitrox", + "Nitrox_ConnectTo": "conectuj se", + "Nitrox_DisconnectedSession": "diconectan sa servera", + "Nitrox_DiscordAccept": "prihvati", + "Nitrox_DiscordDecline": "odbi", + "Nitrox_DiscordInGame": "igra kao {PLAYER}", + "Nitrox_DiscordInGameState": "ronjenje u abyss", + "Nitrox_SilenceChat": "Mutiraj chat", + "Nitrox_SilencedChatNotif": "Chat je sad mutiran", + "Nitrox_StartServer": "Prvo započnite server da bi ušli u svet koji Vi hostujete", + "Nitrox_StreamerSettings": "Mod za streamere", + "Nitrox_TeleportTo": "Teleportuj se do {IGRAČ}", + "Nitrox_TeleportToMe": "Teleportuj {PLAYER} do mene", + "Nitrox_TeleportToMeQuestion": "Teleportuj {IGRAČA} do mene?", + "Nitrox_TeleportToQuestion": "Teleportujte se do {PLAYER}?", + "Nitrox_ThankForPlaying": "Hvala na korištenju Nitroxa!", + "Nitrox_UnableToConnect": "Ne može se konektovati sa udaljenim serverom na:", + "Nitrox_Unmute": "Odmutiraj {PLAYER}", + "Nitrox_UnmuteQuestion": "Odmutirajte {PLAYER}?", + "Nitrox_UnmutedPlayer": "Odmutirali ste {PLAYER}" } diff --git a/Nitrox.Assets.Subnautica/LanguageFiles/sv.json b/Nitrox.Assets.Subnautica/LanguageFiles/sv.json index 580ee31cb0..0c3ee01486 100644 --- a/Nitrox.Assets.Subnautica/LanguageFiles/sv.json +++ b/Nitrox.Assets.Subnautica/LanguageFiles/sv.json @@ -1,45 +1,60 @@ { "Nitrox_AddServer": "Lägg till server", - "Nitrox_AddServerAdd": "Lägg till", - "Nitrox_AddServerHost": "Host:", - "Nitrox_AddServerName": "Namn:", - "Nitrox_AddServerPort": "Port:", "Nitrox_Cancel": "Avbryt", "Nitrox_CommandNotAvailable": "Detta kommando är inte tillgängligt i Nitrox", "Nitrox_ConnectTo": "Anslut till", "Nitrox_DisconnectedSession": "Frånkopplad från servern", "Nitrox_DiscordAccept": "Acceptera", "Nitrox_DiscordDecline": "Neka", + "Nitrox_DiscordInGame": "Spelar som {PLAYER}", + "Nitrox_DiscordInGameState": "Djupdyker", + "Nitrox_DiscordMainMenuState": "Hänger i menyn", + "Nitrox_DiscordMultiplayerMenu": "Vänligen tryck på Multiplayer-knappen i Huvudmenyn om du vill ansluta till en session", "Nitrox_DiscordPressToFocus": "Tryck för att låsa upp", "Nitrox_DiscordRequestText": "Har begärt att få gå med i din session", "Nitrox_EnterName": "Spelar Namn", + "Nitrox_Failure": "Ett fel uppstod", "Nitrox_FirewallInterfering": "Det verkar som om dina brandväggsinställningar stör", "Nitrox_HideIp": "Dölj IP-adresser", - "Nitrox_InvalidUserName": "Vänligen ange ett giltigt spelarnamn!\n\nDen får inte innehålla mellanslag eller tveksamma tecken\nTillåtna tecken: A-Z a-z 0-9 _ . -\nLängd : [3, 25]", + "Nitrox_HidePing": "Dölj Ping", + "Nitrox_InvalidUserName": "Vänligen ange ett giltigt spelarnamn!\n\nDen får inte innehålla mellanslag eller tveksamma tecken\nTillåtna tecken: A-Z a-z 0-9 _ . -\nLängd: [3, 25]", "Nitrox_Join": "Anslut", - "Nitrox_JoinServerFailed": "Gick inte att ansluta till servern", - "Nitrox_JoinServerIpAddress": "Server IP", "Nitrox_JoinServerPassword": "Lösenord:", "Nitrox_JoinServerPasswordHeader": "Serverlösenord krävs", "Nitrox_JoiningSession": "Gå med i multiplayer-session", + "Nitrox_Kick": "Sparka {PLAYER}", + "Nitrox_KickQuestion": "Sparka {PLAYER}?", "Nitrox_LaunchGame": "Startar spel…", "Nitrox_LoadingScreenWarn": "Räkna med spelbrytande buggar", "Nitrox_LostConnection": "Förlorade anslutningen till spelservern", "Nitrox_LostConnectionWarn": "Inte längre ansluten till servern", "Nitrox_Multiplayer": "Multiplayer", "Nitrox_MultiplayerLoaded": "Multiplayer-klient laddad…", - "Nitrox_PlayerColor": "Spelar färg", + "Nitrox_Mute": "Tysta {PLAYER}", + "Nitrox_MuteQuestion": "Tysta {PLAYER}?", + "Nitrox_MutedPlayer": "Tystade {PLAYER}", + "Nitrox_PlayerJoined": "{PLAYER} gick med i spelet.", "Nitrox_PlayerKicked": "Du har blivit sparkad från servern", + "Nitrox_PlayerLeft": "{PLAYER} lämnade spelet.", + "Nitrox_PlayerListTabName": "Spelarlista", "Nitrox_RejectedSessionPolicy": "Reservation avvisades…", + "Nitrox_RemotePlayerObstacle": "En annan spelare är inuti, eller för nära, föremålet för att förstöras.", "Nitrox_RequestingSessionPolicy": "Begär information om sessionspolicy…", - "Nitrox_ServerStopped": "Servern stannade", + "Nitrox_ServerStopped": "Servern stoppades", + "Nitrox_ShowPing": "Visa Ping", "Nitrox_SilenceChat": "Tyst lägg på chatten", "Nitrox_SilencedChatNotif": "Chatten är nu avstängd", "Nitrox_StartServer": "Starta din server först för kunna ansluta till din egen värld", "Nitrox_StreamerSettings": "Streamerläge", - "Nitrox_SubmitPassword": "Skicka in", "Nitrox_SyncingWorld": "Synkroniserar Multiplayer Värld…", + "Nitrox_TeleportTo": "Teleportera till {PLAYER}", + "Nitrox_TeleportToMe": "Teleportera {PLAYER} till mig", + "Nitrox_TeleportToMeQuestion": "Teleportera {PLAYER} till mig?", + "Nitrox_TeleportToQuestion": "Teleportera till {PLAYER}?", + "Nitrox_ThankForPlaying": "Tack för att du använder Nitrox!", "Nitrox_UnableToConnect": "Det går inte att ansluta till fjärrservern på:", + "Nitrox_Unmute": "Slå på ljudet för {PLAYER}", + "Nitrox_UnmuteQuestion": "Avbryta ljudet av {PLAYER}?", "Nitrox_Waiting": "Väntar att gå med i kö…", "Nitrox_WaitingPassword": "Väntar på inmatning av serverlösenord…", "Nitrox_WaitingUserInput": "Väntar på användarinmatning…", diff --git a/Nitrox.Assets.Subnautica/LanguageFiles/th.json b/Nitrox.Assets.Subnautica/LanguageFiles/th.json index 37049513b2..e09ab16d8b 100644 --- a/Nitrox.Assets.Subnautica/LanguageFiles/th.json +++ b/Nitrox.Assets.Subnautica/LanguageFiles/th.json @@ -1,33 +1,63 @@ { "Nitrox_AddServer": "เพิ่มเซิฟเวอร์", - "Nitrox_AddServerAdd": "เพิ่ม", - "Nitrox_AddServerHost": "เจ้าของเซิฟเวอร์", - "Nitrox_AddServerName": "ชื่อ:", - "Nitrox_AddServerPort": "พอร์ต", "Nitrox_Cancel": "ยกเลิก", "Nitrox_CommandNotAvailable": "คำสั่งนี้ไม่มีอยู่ใน Nitrox", "Nitrox_ConnectTo": "เชื่อมต่อกับ", "Nitrox_DisconnectedSession": "ถูกตัดการเชื่อมต่อจากเซิฟเวอร์", "Nitrox_DiscordAccept": "ยอมรับ", "Nitrox_DiscordDecline": "ปฏิเสธ", + "Nitrox_DiscordInGame": "กำลังเล่นเป็น {ผู้เล่น}", + "Nitrox_DiscordInGameState": "กำลังดำสู่ก้นบึ้ง", + "Nitrox_DiscordMainMenuState": "กำลังสำรวจหน้าเมนู", + "Nitrox_DiscordMultiplayerMenu": "กรุณากดปุ่มผู้เล่นหลายคนที่หน้าเมนูถ้าหากคุณอยากจะเข้าร่วม", "Nitrox_DiscordPressToFocus": "กดเพื่อปลดล็อค", "Nitrox_DiscordRequestText": "ได้ขอเข้าร่วมห้องของคุณ", "Nitrox_EnterName": "ใส่ชื่อผู้เล่นของคุณ", + "Nitrox_Failure": "เกิดข้อผิดพลาด", "Nitrox_FirewallInterfering": "ดูเหมือนว่าการตั้งค่า Firewall ของคุณจะเข้ามารบกวน", "Nitrox_HideIp": "ซ่อน IP addresses", "Nitrox_HidePing": "ซ่อนปิง", "Nitrox_InvalidUserName": "โปรดใส่ชื่อให้ถูกต้อง.\n\nชื่อไม่ควรมีตัวเว้นว่าง หรือตัวอักษรพิเศษ\nตัวอักษรที่ใช้ได้: A-Z a-z 0-9 _,-\nความยาว: [3, 25]", "Nitrox_Join": "เข้าร่วม", - "Nitrox_JoinServerFailed": "ไม่สามารถเข้าร่วมเซิฟเวอร์ได้", - "Nitrox_JoinServerIpAddress": "IP เซิฟเวอร์", "Nitrox_JoinServerPassword": "รหัสผ่าน:", "Nitrox_JoinServerPasswordHeader": "ต้องใส่รหัสผ่านของเซิฟเวอร์", "Nitrox_JoiningSession": "กำลังเข้าร่วมห้อง Multiplayer", "Nitrox_Kick": "เตะ {ผู้เล่น}", - "Nitrox_KickQuestion": "เตะ {ผูเล่น}?", + "Nitrox_KickQuestion": "เตะ {ผู้เล่น}?", "Nitrox_LaunchGame": "กำลังเปิดเกม…", "Nitrox_LoadingScreenWarn": "อาจจะเจอบัคที่พังเกมได้", "Nitrox_LostConnection": "ขาดการเชื่อมต่อจากเซิฟเวอร์", "Nitrox_LostConnectionWarn": "ไม่ได้เชื่อมต่อเซิฟเวอร์ต่อไปแล้ว", - "Nitrox_Multiplayer": "ผู้เล่นหลายคน" + "Nitrox_Multiplayer": "ผู้เล่นหลายคน", + "Nitrox_MultiplayerLoaded": "โหลดระบบผู้เล่นหลายคนเสร็จสิ้น…", + "Nitrox_Mute": "ปิดระบบแชท {ผู้เล่น}", + "Nitrox_MuteQuestion": "ปิดระบบแชท {ผู้เล่น}?", + "Nitrox_MutedPlayer": "ปิดระบบแชท {ผู้เล่น}", + "Nitrox_PlayerJoined": "{PLAYER} เข้าร่วมเกม", + "Nitrox_PlayerKicked": "คุณถูกเตะออกจากเซิฟเวอร์", + "Nitrox_PlayerLeft": "{PLAYER} ออกจากเกม.", + "Nitrox_PlayerListTabName": "รายชื่อผู้เล่น", + "Nitrox_RejectedSessionPolicy": "การจองถูกปฎิเสธ…", + "Nitrox_RemotePlayerObstacle": "มีผู้เล่นอยู่ข้างในหรือใกล้เกินไปกับเป้าหมายที่จะแยกโครงสร้าง", + "Nitrox_RequestingSessionPolicy": "กำลังขอข้อมูลนโยบายเซสชัน…", + "Nitrox_ServerStopped": "เซิฟเวอร์ได้ถูกหยุด", + "Nitrox_ShowPing": "แสดงค่าปิง", + "Nitrox_SilenceChat": "ปิดระบบแชท", + "Nitrox_SilencedChatNotif": "ระบบแชทได้ถูกปิดแล้ว", + "Nitrox_StartServer": "เริ่มเซิฟเวอร์ของคุณก่อนเพื่อที่จะเข้าเซิฟเวอร์ของคุณ", + "Nitrox_StreamerSettings": "สตรีมเมอร์โหมด", + "Nitrox_SyncingWorld": "กำลังซิงค์โลกออนไลน์…", + "Nitrox_TeleportTo": "เทเลพอร์ตไปหา", + "Nitrox_TeleportToMe": "เทเลพอร์ต {ผู้เล่น} มาที่ฉัน", + "Nitrox_TeleportToMeQuestion": "เทเลพอร์ต {ผู้เล่น} มาที่ฉัน?", + "Nitrox_TeleportToQuestion": "เทเลพอร์ตไปหา {ผู้เล่น}?", + "Nitrox_ThankForPlaying": "ขอบคุณที่ใช้ Nitrox!", + "Nitrox_UnableToConnect": "ไม่สามารถเชี่ยมต่อกับเซิฟเวอร์ที่กำหนดไว้:", + "Nitrox_Unmute": "ยกเลิกการปิดแชท {ผู้เล่น}", + "Nitrox_UnmuteQuestion": "ยกเลิกการปิดแชท {ผู้เล่น}?", + "Nitrox_UnmutedPlayer": "ยกเลิกการปิดแชท {ผู้เล่น}", + "Nitrox_Waiting": "กำลังต่อคิว…", + "Nitrox_WaitingPassword": "กำลังรอการใส่พาสเวิร์ดของเซิฟเวอร์…", + "Nitrox_WaitingUserInput": "กำลังรอผู้ใช้งานป้อนข้อมูล…", + "Nitrox_WorldSettling": "กำลังรอการตั้งค่าของโลก…" } diff --git a/Nitrox.Assets.Subnautica/LanguageFiles/tr.json b/Nitrox.Assets.Subnautica/LanguageFiles/tr.json index 05a79225a1..bfff3062ec 100644 --- a/Nitrox.Assets.Subnautica/LanguageFiles/tr.json +++ b/Nitrox.Assets.Subnautica/LanguageFiles/tr.json @@ -1,45 +1,79 @@ { "Nitrox_AddServer": "Sunucu Ekle", - "Nitrox_AddServerAdd": "Ekle", - "Nitrox_AddServerHost": "Sunucu:", - "Nitrox_AddServerName": "Ad:", - "Nitrox_AddServerPort": "Bağlantı Noktası:", + "Nitrox_BuildingDesyncDetected": "Sunucu, yerel istemcinin yapılarıyla uyumsuzluk tespit etti (Nitrox ayarlarına giderek yeniden senkronizasyon isteği gönderin)", + "Nitrox_BuildingSettings": "Üs İnşası", "Nitrox_Cancel": "İptal", "Nitrox_CommandNotAvailable": "Bu komut Nitrox'ta kullanılabilir değil", "Nitrox_ConnectTo": "Sunucuya Bağlan", + "Nitrox_DenyOwnershipHand": "Başka bir oyuncu bu nesne ile etkileşim halinde", "Nitrox_DisconnectedSession": "Sunucu bağlantısı kesildi", "Nitrox_DiscordAccept": "Kabul et", "Nitrox_DiscordDecline": "Reddet", + "Nitrox_DiscordInGame": "{PLAYER} olarak oynanıyor", + "Nitrox_DiscordInGameState": "Boşluğa dalıyor", + "Nitrox_DiscordMainMenuState": "Menü de geziniyor", + "Nitrox_DiscordMultiplayerMenu": "Eğer bir oturuma katırlmak istiyorsanız lütfen ana menüdeki çoklu oyuncu düğmesine basın", "Nitrox_DiscordPressToFocus": "Kilidi açmak için basın", "Nitrox_DiscordRequestText": "Oturumunuza katılmak istedi", "Nitrox_EnterName": "Oyuncu adınızı girin", + "Nitrox_ErrorDesyncDetected": "[Güvenli Bina Yapma] Bu üs şu anda uyumsuz durumda, bu yüzden buna değişiklik yapamazsınız, yapabilmeniz için binaları yeniden senkronize etmelisiniz (Nitrox ayarlarından)", + "Nitrox_ErrorRecentBuildUpdate": "Başka bir oyuncu tarafından yakın zamanda güncellenen bir üssü değiştiremezsiniz", + "Nitrox_Failure": "Bir hata oluştu", + "Nitrox_FinishedResyncRequest": "{COUNT} varlık için senkronizasyon {TIME} ms sürdü", "Nitrox_FirewallInterfering": "Güvenlik duvarı ayarları düzgün yapılmamış görünüyor", "Nitrox_HideIp": "IP adreslerini gizle", + "Nitrox_HidePing": "Bildirileri gizle", + "Nitrox_IntroUWEPresents": "UNKNOWN WORLDS ENTERTAINMENT\n&\nTHE NITROX-TEAM\n\nSUNAR", + "Nitrox_IntroWaitingPartner": "Bir ortağın katılmasını bekliyor\n\nBeklemeyi atlamak için {0}'e basın", "Nitrox_InvalidUserName": "Lütfen geçerli bir kullanıcı adı girin.\n\nBoşluk veya özel karakter içermemelidir\nİzin verilen karakterler: A-Z a-z 0-9 _ . -\nUzunluk: [3, 25]", "Nitrox_Join": "Katıl", - "Nitrox_JoinServerFailed": "Sunucuya bağlanılamadı", - "Nitrox_JoinServerIpAddress": "Sunucu IP'si", "Nitrox_JoinServerPassword": "Parola:", "Nitrox_JoinServerPasswordHeader": "Sunucu parolası gerekli", "Nitrox_JoiningSession": "Sunucuya Bağlanılıyor", + "Nitrox_Kick": "{PLAYER} oyunucusunu at", + "Nitrox_KickQuestion": "{PLAYER} Oyuncusunu at?", "Nitrox_LaunchGame": "Oyun başlatılıyor…", "Nitrox_LoadingScreenWarn": "Oyunu bozacak hatalar", "Nitrox_LostConnection": "Oyun sunucusuyla bağlantı kesildi", "Nitrox_LostConnectionWarn": "Artık sunucuya bağlı değil", "Nitrox_Multiplayer": "Çok Oyunculu", "Nitrox_MultiplayerLoaded": "Çok oyunculu istemci yüklendi…", - "Nitrox_PlayerColor": "Oyuncu Rengi", + "Nitrox_Mute": "{PLAYER} oyuncusunu sustur", + "Nitrox_MuteQuestion": "{PLAYER} oyuncusunu sustur?", + "Nitrox_MutedPlayer": "{PLAYER} oyunucusu susturuldu", + "Nitrox_OutOfDateClient": "Nitrox kurulumunuz güncel değil. Sunucu: {serverVersion}, Sizininki: {localVersion}.", + "Nitrox_OutOfDateServer": "Sunucu, eski bir Nitrox sürümünü çalıştırıyor. Sunucu yöneticisinden sunucuyu güncellemesini veya sizin Nitrox kurulumunuzu eski bir sürüme düşürmesini isteyin. Sunucu: {serverVersion}, Sizininki: {localVersion}.", + "Nitrox_PlayerDied": "{PLAYER} öldü", + "Nitrox_PlayerDisconnected": "{PLAYER} oyundan ayrıldı", + "Nitrox_PlayerJoined": "{PLAYER} oyuna katıldı.", "Nitrox_PlayerKicked": "Sunucudan atıldınız", + "Nitrox_PlayerLeft": "{PLAYER} oyundan ayrıldı.", + "Nitrox_PlayerListTabName": "Oyuncu listesi", "Nitrox_RejectedSessionPolicy": "Rezervasyon reddedildi…", + "Nitrox_RemotePlayerObstacle": "Bir oyuncu yıkılabilecek hedefin içinde veya çok yakınında.", "Nitrox_RequestingSessionPolicy": "Oturum bilgileri alınıyor…", + "Nitrox_ResyncBuildings": "Üs binalarını yeniden senkronize et", + "Nitrox_ResyncOnCooldown": "Yeniden senkronizasyon isteği gönderebilmek için {TIME_LEFT} saniye beklemeniz gerekiyor", + "Nitrox_ResyncRequested": "Üsler için bir senkronizasyon isteği gönderildi", + "Nitrox_ResyncSettings": "Yeniden Senkronizasyon", + "Nitrox_SafeBuilding": "Güvenli yapı", + "Nitrox_SafeBuildingLog": "Güvenli yapı kaydı", "Nitrox_ServerStopped": "Sunucu durduruldu", + "Nitrox_ShowPing": "Ping'i Göster", "Nitrox_SilenceChat": "Sohbeti sessize al", "Nitrox_SilencedChatNotif": "Sohbet artık sessiz", "Nitrox_StartServer": "Kendi dünyanıza katılmak için önce sunucu başlatmalısınız", "Nitrox_StreamerSettings": "Yayıncı modu", - "Nitrox_SubmitPassword": "Gönder", "Nitrox_SyncingWorld": "Dünya Eşzamanlanıyor…", + "Nitrox_TeleportTo": "{PLAYER} oyuncusuna ışınlan", + "Nitrox_TeleportToMe": "{PLAYER} oyuncusunu bana ışınla", + "Nitrox_TeleportToMeQuestion": "{PLAYER} oyuncusunu bana ışınla?", + "Nitrox_TeleportToQuestion": "{PLAYER} oyuncusuna ışınlan?", + "Nitrox_ThankForPlaying": "Nitrox'u kullandığınız için teşekkürler!", "Nitrox_UnableToConnect": "Bu uzak sunucu ile iletişim kurulamıyor:", + "Nitrox_Unmute": "{PLAYER} sesini aç", + "Nitrox_UnmuteQuestion": "{PLAYER} sesini aç?", + "Nitrox_UnmutedPlayer": "{PLAYER} oyuncusunun sesi açıldı", "Nitrox_Waiting": "Katılma kuyruğunda bekleniyor…", "Nitrox_WaitingPassword": "Sunucu parolası girilmesi bekleniyor…", "Nitrox_WaitingUserInput": "Kullanıcı adı girilmesi bekleniyor…", diff --git a/Nitrox.Assets.Subnautica/LanguageFiles/uk.json b/Nitrox.Assets.Subnautica/LanguageFiles/uk.json index c1701fa868..f558e56d3a 100644 --- a/Nitrox.Assets.Subnautica/LanguageFiles/uk.json +++ b/Nitrox.Assets.Subnautica/LanguageFiles/uk.json @@ -1,25 +1,31 @@ { "Nitrox_AddServer": "Додати сервер", - "Nitrox_AddServerAdd": "Додати", - "Nitrox_AddServerHost": "Адреса:", - "Nitrox_AddServerName": "Ім'я:", - "Nitrox_AddServerPort": "Порт:", + "Nitrox_BuildingDesyncDetected": "Сервер виявив десинхронізацію з локальними клієнтськими будівлями(перейдіть до налаштувань Nitrox, щоб надіслати запит на повторну синхронізацію)", + "Nitrox_BuildingSettings": "Налаштування будівель", "Nitrox_Cancel": "Скасувати", "Nitrox_CommandNotAvailable": "Ця команда недоступна в Nitrox", "Nitrox_ConnectTo": "З'єднатися з", "Nitrox_DisconnectedSession": "Від'єднано від сервера", "Nitrox_DiscordAccept": "Прийняти", "Nitrox_DiscordDecline": "Відхилити", + "Nitrox_DiscordInGame": "Грає, як {PLAYER}", + "Nitrox_DiscordInGameState": "Занирює у безодню", + "Nitrox_DiscordMainMenuState": "Сидить у меню", + "Nitrox_DiscordMultiplayerMenu": "Будь ласка нажміть на кнопку \"Багатокористувацька гра\" у головному меню, якщо ви хочете доєднатися до сеансу гри", "Nitrox_DiscordPressToFocus": "Натисніть для розблокування", "Nitrox_DiscordRequestText": "Запитує на приєднання до вашого сеансу", "Nitrox_EnterName": "Введіть своє ім'я гравця", + "Nitrox_ErrorDesyncDetected": "[Безпечне будівництво] Ця база наразі десинхронізована, тому ви не можете змінити її, доки не синхронизуєте повторно будівлі (у налаштуваннях Nitrox)", + "Nitrox_ErrorRecentBuildUpdate": "Неможливо змінити будівлю, яка була нещодавно оновлена іншим гравцем", + "Nitrox_Failure": "Сталася помилка", + "Nitrox_FinishedResyncRequest": "Для повторної синхронізації {COUNT} об’єктів знадобилося {TIME} мс", "Nitrox_FirewallInterfering": "Схоже, що заважають налаштування вашого брандмауера", "Nitrox_HideIp": "Приховати IP-адреси", "Nitrox_HidePing": "Сховати Пінг", + "Nitrox_IntroUWEPresents": "UNKNOWN WORLDS ENTERTAINMENT\nТА\nКОМАНДА NITROX\n\nПРЕЗЕНТУЮТЬ", + "Nitrox_IntroWaitingPartner": "Очікування приєднання іншого гравця\n\nНажміть {0} щоб пропустити очікування", "Nitrox_InvalidUserName": "Будь ласка, введіть припустиме ім'я гравця.\n\nВоно не може містити пробіл чи недозволені символи\nДозволені символи: A-Z a-z 0-9 _.-\nДовжина: [3, 25]", "Nitrox_Join": "Приєднатись", - "Nitrox_JoinServerFailed": "Не вдалося приєднатися до сервера", - "Nitrox_JoinServerIpAddress": "IP сервера", "Nitrox_JoinServerPassword": "Пароль:", "Nitrox_JoinServerPasswordHeader": "Потрібен пароль сервера", "Nitrox_JoiningSession": "Приєднання до багатокористувацької гри", @@ -34,23 +40,35 @@ "Nitrox_Mute": "Вимкнути звук {PLAYER}", "Nitrox_MuteQuestion": "Заглушити гравця {PLAYER}?", "Nitrox_MutedPlayer": "Звук вимкнено {PLAYER}", - "Nitrox_PlayerColor": "Колір гравця", + "Nitrox_OutOfDateClient": "Ваша версія Nitrox застаріла. Сервер: {serverVersion}, Ваша: {localVersion}.", + "Nitrox_OutOfDateServer": "У сервера застаріла версія Nitrox. Попросіть адміністратора сервера оновити версію сервера або змініть вашу версію Nitrox. Сервер: {serverVersion}, Ваша: {localVersion}.", + "Nitrox_PlayerDied": "{PLAYER} помер", + "Nitrox_PlayerDisconnected": "{PLAYER} відключився", + "Nitrox_PlayerJoined": "{PLAYER} приєднався до гри.", "Nitrox_PlayerKicked": "Вас виштовхнули з сервера", + "Nitrox_PlayerLeft": "{PLAYER} вийшов з гри.", "Nitrox_PlayerListTabName": "Список гравців", "Nitrox_RejectedSessionPolicy": "Бронювання відхилено…", + "Nitrox_RemotePlayerObstacle": "Інший гравець або всередині, або занадто близько до цілі, що розбирається.", "Nitrox_RequestingSessionPolicy": "Запит інформації про політику сеансу…", + "Nitrox_ResyncBuildings": "Синхронізувати будівлі бази", + "Nitrox_ResyncOnCooldown": "Щоб надіслати запит на повторну синхронізацію, потрібно зачекати {TIME_LEFT} с", + "Nitrox_ResyncRequested": "Помилка повторного запиту синхронізації баз", + "Nitrox_ResyncSettings": "Синхронізація", + "Nitrox_SafeBuilding": "Безпечне будівництво", + "Nitrox_SafeBuildingLog": "Журнал безпечного будівництва", "Nitrox_ServerStopped": "Сервер зупинено", "Nitrox_ShowPing": "Показати Пінг", "Nitrox_SilenceChat": "Вимкнути звук у чаті", "Nitrox_SilencedChatNotif": "Звук у чаті вимкнено", "Nitrox_StartServer": "Спершу запустіть свій сервер, щоб приєднатися до самостійно розміщеного світу", "Nitrox_StreamerSettings": "Режим стримера", - "Nitrox_SubmitPassword": "Прийняти", "Nitrox_SyncingWorld": "Синхронізація багатокористувацького світу…", "Nitrox_TeleportTo": "Телепортуватися до {PLAYER}", "Nitrox_TeleportToMe": "Телепортувати {PLAYER} до мене", "Nitrox_TeleportToMeQuestion": "Перемістити гравця {PLAYER} до себе ?", "Nitrox_TeleportToQuestion": "Переміститися до гравця {PLAYER} ?", + "Nitrox_ThankForPlaying": "Дякуємо за використання Nitrox!", "Nitrox_UnableToConnect": "Не вдається зв'язатися з віддаленим сервером за адресою:", "Nitrox_Unmute": "Увімкнути звук {PLAYER}", "Nitrox_UnmuteQuestion": "Увімкнути звук гравця {PLAYER}?", diff --git a/Nitrox.Assets.Subnautica/LanguageFiles/vi.json b/Nitrox.Assets.Subnautica/LanguageFiles/vi.json index 1365f4db64..f72d42fc08 100644 --- a/Nitrox.Assets.Subnautica/LanguageFiles/vi.json +++ b/Nitrox.Assets.Subnautica/LanguageFiles/vi.json @@ -1,56 +1,73 @@ { "Nitrox_AddServer": "Thêm Server", - "Nitrox_AddServerAdd": "Thêm", - "Nitrox_AddServerHost": "Host:", - "Nitrox_AddServerName": "Tên:", - "Nitrox_AddServerPort": "Cổng:", + "Nitrox_BuildingDesyncDetected": "Máy chủ đã phát hiện quá trình không đồng bộ hóa với các tòa nhà của máy khách cục bộ (đi tới cài đặt Nitrox để yêu cầu đồng bộ lại)", + "Nitrox_BuildingSettings": "Xây dựng cơ sở", "Nitrox_Cancel": "Hủy", "Nitrox_CommandNotAvailable": "Lệnh này không khả dụng trong Nitrox", "Nitrox_ConnectTo": "Kết nối vào", "Nitrox_DisconnectedSession": "Ngắt kết nối với server", "Nitrox_DiscordAccept": "Chấp nhận", "Nitrox_DiscordDecline": "Từ chối", + "Nitrox_DiscordInGame": "Đang tham gia với {PLAYER}", + "Nitrox_DiscordInGameState": "Lặn xuống vực sâu", + "Nitrox_DiscordMainMenuState": "Ẩn trong menu", + "Nitrox_DiscordMultiplayerMenu": "Vui lòng nhấn vào nút Nhiều người chơi trong MainMenu nếu bạn muốn tham gia một phiên", "Nitrox_DiscordPressToFocus": "Bấm để mở khóa", "Nitrox_DiscordRequestText": "yêu cầu tham gia server", "Nitrox_EnterName": "Nhập vào tên người chơi", + "Nitrox_ErrorDesyncDetected": "[Khu vực an toàn] Căn cứ này hiện không được đồng bộ hóa nên bạn không thể sửa đổi nó trừ khi bạn đồng bộ lại các tòa nhà (trong cài đặt Nitrox)", + "Nitrox_ErrorRecentBuildUpdate": "Không thể chỉnh sửa căn cứ đã được thao tác bởi người chơi khác", + "Nitrox_Failure": "Đã xảy ra lỗi", + "Nitrox_FinishedResyncRequest": "Mất {TIME}ms để đồng bộ hóa {COUNT} thực thể", "Nitrox_FirewallInterfering": "Tường lửa của bạn có thể đang can thiệp", "Nitrox_HideIp": "Ẩn địa chỉ IP", "Nitrox_HidePing": "Ẩn ping", + "Nitrox_IntroWaitingPartner": "Đang đợi người tham gia\n\nNhấn {0} để bỏ qua thời gian đợi", "Nitrox_InvalidUserName": "Hãy nhập tên hợp lệ\n\nTên người chơi không thể chứa khoảng cách hoặc ký tự không rõ\nCác ký tự cho phép: A-Z a-z 0-9 _.-\nĐộ dài: [3, 25]", "Nitrox_Join": "Gia nhập", - "Nitrox_JoinServerFailed": "Không thể kết nối tới máy chủ", - "Nitrox_JoinServerIpAddress": "IP của máy chủ", "Nitrox_JoinServerPassword": "Mật khẩu:", "Nitrox_JoinServerPasswordHeader": "Cần có mật khẩu máy chủ", - "Nitrox_JoiningSession": "Đang gia nhập phiên nhiều người chơi", + "Nitrox_JoiningSession": "Đang tham gia phiên nhiều người chơi", "Nitrox_Kick": "Đá {PLAYER}", "Nitrox_KickQuestion": "Đá {PLAYER}?", "Nitrox_LaunchGame": "Khởi động game…", "Nitrox_LoadingScreenWarn": "Vẫn còn nhiều lỗi lớn trong game", "Nitrox_LostConnection": "Mất kết nối tới máy chủ", "Nitrox_LostConnectionWarn": "Đã mất kết nối", - "Nitrox_Multiplayer": "Đa người chơi", - "Nitrox_MultiplayerLoaded": "Đã tải xong client đa người chơi…", + "Nitrox_Multiplayer": "Nhiều người chơi", + "Nitrox_MultiplayerLoaded": "Đã tải client nhiều người chơi…", "Nitrox_Mute": "Tắt tiếng {PLAYER}", "Nitrox_MuteQuestion": "Tắt tiếng {PLAYER}?", "Nitrox_MutedPlayer": "Đã tắt tiếng {PLAYER}", - "Nitrox_PlayerColor": "Màu của người chơi", + "Nitrox_OutOfDateClient": "Phiên bản cài đặt Nitrox của bạn đã lỗi thời. Máy chủ: {serverVersion}, phiên bản của bạn: {localVersion}.", + "Nitrox_OutOfDateServer": "Máy chủ chạy phiên bản cũ hơn của Nitrox. Yêu cầu quản trị viên máy chủ nâng cấp máy chủ hoặc hạ cấp cài đặt Nitrox của bạn. Máy chủ: {serverVersion}, phiên bản của bạn: {localVersion}.", + "Nitrox_PlayerDied": "{PLAYER} chết", + "Nitrox_PlayerDisconnected": "{PLAYER} đã bị ngắt kết nối", + "Nitrox_PlayerJoined": "{PLAYER} đã tham gia trò chơi.", "Nitrox_PlayerKicked": "Bạn đã bị đá khỏi sever", + "Nitrox_PlayerLeft": "{PLAYER} đã rời khỏi trò chơi.", "Nitrox_PlayerListTabName": "Danh sách người chơi", "Nitrox_RejectedSessionPolicy": "Từ chối giữ chỗ…", + "Nitrox_RemotePlayerObstacle": "Một người chơi khác đang ở bên trong hoặc quá gần mục tiêu có thể phá hủy.", "Nitrox_RequestingSessionPolicy": "Đang yêu cầu thông tin về chính sách của phiên…", + "Nitrox_ResyncBuildings": "Đồng bộ lại các cơ sở xây dựng", + "Nitrox_ResyncOnCooldown": "Bạn cần đợi {TIME_LEFT} giây để có thể gửi yêu cầu đồng bộ lại", + "Nitrox_ResyncRequested": "Đã đưa ra yêu cầu đồng bộ lại cho các căn cứ", + "Nitrox_ResyncSettings": "Đồng bộ hóa lại", + "Nitrox_SafeBuilding": "Khu vực an toàn", + "Nitrox_SafeBuildingLog": "Nhật ký xây dựng an toàn", "Nitrox_ServerStopped": "Sever đã ngừng", "Nitrox_ShowPing": "Hiển thị ping", "Nitrox_SilenceChat": "Tắt trò chuyện", "Nitrox_SilencedChatNotif": "Trò chuyện đã được tắt", "Nitrox_StartServer": "Khởi động máy chủ của bạn trước để tham gia thế giới được tự tổ chức bởi bạn", "Nitrox_StreamerSettings": "Chế độ phát trực tiếp", - "Nitrox_SubmitPassword": "Gửi", - "Nitrox_SyncingWorld": "Đồng bộ hóa thế giới đa người chơi…", + "Nitrox_SyncingWorld": "Đồng bộ thế giới nhiều người chơi…", "Nitrox_TeleportTo": "Dịch chuyển đến {PLAYER}", "Nitrox_TeleportToMe": "Dịch chuyển {PLAYER} đến bản thân", "Nitrox_TeleportToMeQuestion": "Dịch chuyển {PLAYER} đến bản thân?", "Nitrox_TeleportToQuestion": "Dịch chuyển đến {PLAYER}?", + "Nitrox_ThankForPlaying": "Cảm ơn đã sử dụng Nitrox!", "Nitrox_UnableToConnect": "Không thể liên hệ tới máy chủ từ xa tại:", "Nitrox_Unmute": "Bật tiếng {PLAYER}", "Nitrox_UnmuteQuestion": "Bật tiếng {PLAYER}?", diff --git a/Nitrox.Assets.Subnautica/LanguageFiles/zh-Hans.json b/Nitrox.Assets.Subnautica/LanguageFiles/zh-Hans.json index aa6d91f124..2491a30370 100644 --- a/Nitrox.Assets.Subnautica/LanguageFiles/zh-Hans.json +++ b/Nitrox.Assets.Subnautica/LanguageFiles/zh-Hans.json @@ -1,60 +1,63 @@ { "Nitrox_AddServer": "添加服务器", - "Nitrox_AddServerAdd": "添加", - "Nitrox_AddServerHost": "主机:", - "Nitrox_AddServerName": "名称:", - "Nitrox_AddServerPort": "端口:", "Nitrox_Cancel": "取消", - "Nitrox_CommandNotAvailable": "Nitrox: 该指令不可用", - "Nitrox_ConnectTo": "连接至", - "Nitrox_DisconnectedSession": "离开服务器", + "Nitrox_CommandNotAvailable": "该指令不能在Nitrox使用", + "Nitrox_Confirm": "确定", + "Nitrox_ConnectTo": "连接到", + "Nitrox_DenyOwnershipHand": "另一名玩家正在与该物体互动", + "Nitrox_DisconnectedSession": "已离开服务器", "Nitrox_DiscordAccept": "接受", "Nitrox_DiscordDecline": "拒绝", + "Nitrox_DiscordInGame": "正在以{PLAYER}游玩", + "Nitrox_DiscordInGameState": "正在潜入深渊", + "Nitrox_DiscordMainMenuState": "正处于主屏", + "Nitrox_DiscordMultiplayerMenu": "请选择主屏中的多人游玩以便加入服务器", "Nitrox_DiscordPressToFocus": "点击解锁", - "Nitrox_DiscordRequestText": "请求加入您的会话", - "Nitrox_EnterName": "输入您的玩家名", - "Nitrox_FirewallInterfering": "您的防火墙设置可能存在干扰", + "Nitrox_DiscordRequestText": "希望加入您的服务器", + "Nitrox_EnterName": "请输入您的名称", + "Nitrox_Failure": "发生了错误", + "Nitrox_FirewallInterfering": "您的防火墙设置可能阻止了连接", "Nitrox_HideIp": "隐藏 IP 地址", "Nitrox_HidePing": "隐藏ping", - "Nitrox_InvalidUserName": "请输入一个合法的玩家名\n\n不含空格和特殊字符\n允许的字符: A-Z a-z 0-9 _ . -\n长度限制: 3~25", + "Nitrox_InvalidUserName": "请输入有效的名称\n\n不能含有空格或特殊字符\n允许的字符: A-Z a-z 0-9 _ . -\n长度限制: [3, 25]", "Nitrox_Join": "加入", - "Nitrox_JoinServerFailed": "无法加入服务器", - "Nitrox_JoinServerIpAddress": "服务器 IP", "Nitrox_JoinServerPassword": "密码:", - "Nitrox_JoinServerPasswordHeader": "服务器需要密码", - "Nitrox_JoiningSession": "正在加入多人会话", - "Nitrox_Kick": "踢出 {PLAYER}", - "Nitrox_KickQuestion": "是否踢出 {PLAYER}?", + "Nitrox_JoinServerPasswordHeader": "需要服务器密码", + "Nitrox_JoiningSession": "正在加入服务器", + "Nitrox_Kick": "踢出{PLAYER}", + "Nitrox_KickQuestion": "是否踢出{PLAYER}?", "Nitrox_LaunchGame": "正在启动游戏…", - "Nitrox_LoadingScreenWarn": "期待破坏游戏的 bugs", + "Nitrox_LoadingScreenWarn": "存在漏洞", "Nitrox_LostConnection": "失去与服务器的连接", - "Nitrox_LostConnectionWarn": "与服务器连接不稳定", + "Nitrox_LostConnectionWarn": "与服务器的连接已断开", "Nitrox_Multiplayer": "多人游戏", - "Nitrox_MultiplayerLoaded": "联机客户端加载…", - "Nitrox_Mute": "禁言 {PLAYER}", - "Nitrox_MuteQuestion": "是否禁言 {PLAYER}?", - "Nitrox_MutedPlayer": "已禁言 {PLAYER}", - "Nitrox_PlayerColor": "玩家颜色", - "Nitrox_PlayerKicked": "您已被请出服务器", + "Nitrox_MultiplayerLoaded": "已加载联机客户端…", + "Nitrox_Mute": "禁言{PLAYER}", + "Nitrox_MuteQuestion": "是否禁言{PLAYER}?", + "Nitrox_MutedPlayer": "已禁言{PLAYER}", + "Nitrox_PlayerJoined": "{PLAYER}已加入游戏。", + "Nitrox_PlayerKicked": "您已被踢出服务器", + "Nitrox_PlayerLeft": "{PLAYER}已离开游戏。", "Nitrox_PlayerListTabName": "玩家列表", "Nitrox_RejectedSessionPolicy": "会话配置被拒绝…", + "Nitrox_RemotePlayerObstacle": "另一个玩家距离解构目标太近了。", "Nitrox_RequestingSessionPolicy": "正在请求会话配置信息…", "Nitrox_ServerStopped": "服务器已关闭", "Nitrox_ShowPing": "显示ping", - "Nitrox_SilenceChat": "禁言聊天", - "Nitrox_SilencedChatNotif": "聊天已禁言", - "Nitrox_StartServer": "首先启动您的服务器以加入您自己的世界", + "Nitrox_SilenceChat": "将聊天设为静音", + "Nitrox_SilencedChatNotif": "聊天已被静音", + "Nitrox_StartServer": "请先启动您的服务器以加入世界", "Nitrox_StreamerSettings": "主播模式", - "Nitrox_SubmitPassword": "提交", "Nitrox_SyncingWorld": "同步多人世界中…", - "Nitrox_TeleportTo": "传送至 {PLAYER}", - "Nitrox_TeleportToMe": "将 {PLAYER} 传送到我身边", - "Nitrox_TeleportToMeQuestion": "将 {PLAYER} 传送到我身边?", - "Nitrox_TeleportToQuestion": "传送至 {PLAYER}?", - "Nitrox_UnableToConnect": "无法连接至远程服务器:", - "Nitrox_Unmute": "解除禁言 {PLAYER}", - "Nitrox_UnmuteQuestion": "是否解除禁言 {PLAYER}?", - "Nitrox_UnmutedPlayer": "已取消禁言 {PLAYER}", + "Nitrox_TeleportTo": "传送至{PLAYER}", + "Nitrox_TeleportToMe": "传送{PLAYER}到我身边", + "Nitrox_TeleportToMeQuestion": "是否传送{PLAYER}到我身边?", + "Nitrox_TeleportToQuestion": "是否传送至{PLAYER}?", + "Nitrox_ThankForPlaying": "感谢您使用Nitrox!", + "Nitrox_UnableToConnect": "无法连接至远程服务器:", + "Nitrox_Unmute": "解除{PLAYER}的禁言", + "Nitrox_UnmuteQuestion": "是否解除{PLAYER}的禁言?", + "Nitrox_UnmutedPlayer": "已解除{PLAYER}的禁言", "Nitrox_Waiting": "等待加入中…", "Nitrox_WaitingPassword": "等待输入服务器密码中…", "Nitrox_WaitingUserInput": "等待用户输入中…", diff --git a/Nitrox.Assets.Subnautica/LanguageFiles/zh-Hant.json b/Nitrox.Assets.Subnautica/LanguageFiles/zh-Hant.json new file mode 100644 index 0000000000..e7acf06c20 --- /dev/null +++ b/Nitrox.Assets.Subnautica/LanguageFiles/zh-Hant.json @@ -0,0 +1,63 @@ +{ + "Nitrox_AddServer": "添加服務器", + "Nitrox_Cancel": "取消", + "Nitrox_CommandNotAvailable": "該指令不能在Nitrox使用", + "Nitrox_ConnectTo": "連接到", + "Nitrox_DisconnectedSession": "已離開服務器", + "Nitrox_DiscordAccept": "接受", + "Nitrox_DiscordDecline": "拒絕", + "Nitrox_DiscordInGame": "正在以{PLAYER}遊玩", + "Nitrox_DiscordInGameState": "正在潛入深淵", + "Nitrox_DiscordMainMenuState": "正處於主屏", + "Nitrox_DiscordMultiplayerMenu": "請選擇主屏中的多人游玩以便加入服務器", + "Nitrox_DiscordPressToFocus": "點擊解鎖", + "Nitrox_DiscordRequestText": "希望加入您的服務器", + "Nitrox_EnterName": "請輸入您的名稱", + "Nitrox_Failure": "發生了錯誤", + "Nitrox_FirewallInterfering": "您的防火墻設置可能阻止了連接", + "Nitrox_HideIp": "隱藏IP地址", + "Nitrox_HidePing": "隱藏Ping", + "Nitrox_InvalidUserName": "請輸入有效的名稱\n\n不能含有空格或特殊字符\n允許的字符:A-Z a-z 0-9 _ . -\n長度限制:[3, 25]", + "Nitrox_Join": "加入", + "Nitrox_JoinServerPassword": "密碼:", + "Nitrox_JoinServerPasswordHeader": "需要服務器密碼", + "Nitrox_JoiningSession": "正在加入服務器", + "Nitrox_Kick": "踢出{PLAYER}", + "Nitrox_KickQuestion": "是否踢出{PLAYER}?", + "Nitrox_LaunchGame": "正在啓動游戲…", + "Nitrox_LoadingScreenWarn": "存在漏洞", + "Nitrox_LostConnection": "失去與服務器的連接", + "Nitrox_LostConnectionWarn": "與服務器的連接已斷開", + "Nitrox_Multiplayer": "多人遊戲", + "Nitrox_MultiplayerLoaded": "已加載聯機客戶端…", + "Nitrox_Mute": "禁言{PLAYER}", + "Nitrox_MuteQuestion": "是否禁言{PLAYER}?", + "Nitrox_MutedPlayer": "已禁言{PLAYER}", + "Nitrox_PlayerJoined": "{PLAYER}已加入遊戲。", + "Nitrox_PlayerKicked": "您已被踢出服務器", + "Nitrox_PlayerLeft": "{PLAYER}已離開遊戲。", + "Nitrox_PlayerListTabName": "玩家列表", + "Nitrox_RejectedSessionPolicy": "會話配置被拒绝…", + "Nitrox_RemotePlayerObstacle": "另一个玩家距離解構目標太近了。", + "Nitrox_RequestingSessionPolicy": "正在請求會話配置信息…", + "Nitrox_ServerStopped": "服務器已關閉", + "Nitrox_ShowPing": "顯示Ping", + "Nitrox_SilenceChat": "將聊天設為靜音", + "Nitrox_SilencedChatNotif": "聊天已被靜音", + "Nitrox_StartServer": "請先啓動您的服務器以加入世界", + "Nitrox_StreamerSettings": "主播模式", + "Nitrox_SyncingWorld": "同步多人世界中…", + "Nitrox_TeleportTo": "傳送至{PLAYER}", + "Nitrox_TeleportToMe": "傳送{PLAYER}到我身邊", + "Nitrox_TeleportToMeQuestion": "是否傳送{PLAYER}到我身邊?", + "Nitrox_TeleportToQuestion": "是否傳送至{PLAYER}?", + "Nitrox_ThankForPlaying": "感謝您使用Nitrox!", + "Nitrox_UnableToConnect": "無法鏈接至遠程服務器:", + "Nitrox_Unmute": "解除{PLAYER}的禁言", + "Nitrox_UnmuteQuestion": "是否解除{PLAYER}的禁言?", + "Nitrox_UnmutedPlayer": "已解除{PLAYER}的禁言", + "Nitrox_Waiting": "等待加入中…", + "Nitrox_WaitingPassword": "等待輸入服務器密碼中…", + "Nitrox_WaitingUserInput": "等等用戶輸入中…", + "Nitrox_WorldSettling": "等待世界生成中…" +} diff --git a/NitroxClient/Resources/soundsWhitelist.csv b/Nitrox.Assets.Subnautica/Resources/SoundWhitelist_Subnautica.csv similarity index 96% rename from NitroxClient/Resources/soundsWhitelist.csv rename to Nitrox.Assets.Subnautica/Resources/SoundWhitelist_Subnautica.csv index 4868e1e5f4..8126ea99e7 100644 --- a/NitroxClient/Resources/soundsWhitelist.csv +++ b/Nitrox.Assets.Subnautica/Resources/SoundWhitelist_Subnautica.csv @@ -1,5 +1,5 @@ #List of every sound and if it should be synced;;; -#Eventpath;Should be syned;Should ignore subroot;Sound radius +#Eventpath;Should be synced;Should ignore subroot;Sound radius ;;; event:/creature/bird_small/flap;false;false;0 event:/creature/bird_small/idle;false;false;0 @@ -265,10 +265,10 @@ event:/player/adviseSelfScan;false;false;0 event:/player/aurora_warning_1;false;false;0 event:/player/aurora_warning_2;false;false;0 event:/player/aurora_warning_3;false;false;0 -event:/player/breathing;false;false;20 -event:/player/bubbles;false;false;20 +event:/player/breathing;true;false;20 +event:/player/bubbles;true;false;20 event:/player/cold_damage;true;false;20 -event:/player/coughing;true;false;20 +event:/player/coughing;false;false;0 event:/player/cube terminal_close;false;false;0 event:/player/cube terminal_open;false;false;0 event:/player/cube terminal_use;false;false;0 @@ -281,9 +281,9 @@ event:/player/enzyme_cure;false;false;0 event:/player/food_critical;false;false;0 event:/player/food_low;false;false;0 event:/player/food_very_low;false;false;0 -event:/player/footstep_dirt;true;false;20 -event:/player/footstep_metal;true;false;20 -event:/player/footstep_precursor_base;true;false;20 +event:/player/footstep_dirt;false;false;0 +event:/player/footstep_metal;false;false;0 +event:/player/footstep_precursor_base;false;false;0 event:/player/goal_airsack;false;false;0 event:/player/goal_BiomeKelpForest;false;false;0 event:/player/goal_BiomePrecursorGunUpper;false;false;0 @@ -322,10 +322,10 @@ event:/player/key_terminal_use;false;false;0 event:/player/new_creature;false;false;0 event:/player/oxygen_10_sec;false;false;0 event:/player/oxygen_30_sec;false;false;0 -event:/player/Pain;true;false;20 -event:/player/Pain_no_tank;true;false;20 -event:/player/pain_no_tank_light;true;false;20 -event:/player/Pain_surface;true;false;20 +event:/player/Pain;false;false;0 +event:/player/Pain_no_tank;false;false;0 +event:/player/pain_no_tank_light;false;false;0 +event:/player/Pain_surface;false;false;0 event:/player/Precursor_Gun_ControlRoom;false;false;0 event:/player/Precursor_Gun_DisableDenied;false;false;0 event:/player/Precursor_Gun_LostRiverHint;false;false;0 @@ -346,7 +346,7 @@ event:/player/selfScan4;false;false;0 event:/player/selfScan5;false;false;0 event:/player/signal_upload;false;false;0 event:/player/start_freedive;false;false;0 -event:/player/start_freedive_splash;true;false;30 +event:/player/start_freedive_splash;false;false;0 event:/player/step;true;false;20 event:/player/stillsuit_equipped;false;false;0 event:/player/story/Aurora_RingRoom_Terminal2;false;false;0 @@ -604,24 +604,24 @@ event:/sub/drone/connected;false;false;0 event:/sub/drone/connecting_loop;false;false;0 event:/sub/drone/idle;false;false;0 event:/sub/drone/motor_loop;false;false;0 -event:/sub/exo/claw_hit_fish;true;true;20 -event:/sub/exo/claw_hit_terain;true;true;20 -event:/sub/exo/claw_pickup;true;true;20 -event:/sub/exo/claw_punch;true;true;20 +event:/sub/exo/claw_hit_fish;true;true;40 +event:/sub/exo/claw_hit_terain;true;true;40 +event:/sub/exo/claw_pickup;true;true;40 +event:/sub/exo/claw_punch;true;true;40 event:/sub/exo/dock_exo_cyclops;false;false;0 event:/sub/exo/dock_exo_moonpool;false;false;0 -event:/sub/exo/drill_hit_loop;true;true;20 -event:/sub/exo/drill_loop;true;true;20 +event:/sub/exo/drill_hit_loop;true;true;50 +event:/sub/exo/drill_loop;true;true;50 event:/sub/exo/enter_exo;false;false;0 -event:/sub/exo/hook_hit;true;true;20 -event:/sub/exo/hook_loop;true;true;20 -event:/sub/exo/hook_shoot;true;true;20 +event:/sub/exo/hook_hit;true;true;50 +event:/sub/exo/hook_loop;true;true;50 +event:/sub/exo/hook_shoot;true;true;50 event:/sub/exo/interior_loop;false;false;0 -event:/sub/exo/jets_empty;false;false;0 -event:/sub/exo/jets_loop;true;true;50 -event:/sub/exo/jump;true;true;50 -event:/sub/exo/land;true;true;50 -event:/sub/exo/step;true;true;50 +event:/sub/exo/jets_empty;false;false;100 +event:/sub/exo/jets_loop;false;false;100 +event:/sub/exo/jump;true;true;90 +event:/sub/exo/land;true;true;90 +event:/sub/exo/step;false;false;90 event:/sub/exo/undock_exo_cyclops;false;false;0 event:/sub/exo/undock_exo_moonpool;false;false;0 event:/sub/exo/welcome;false;false;0 @@ -686,12 +686,12 @@ event:/sub/seamoth/interior_loop;false;false;0 event:/sub/seamoth/pulse;false;false;0 event:/sub/seamoth/pulse_charge_loop;false;false;0 event:/sub/seamoth/seaglide_equip;true;true;10 -event:/sub/seamoth/seaglide_light_off;true;true;7 -event:/sub/seamoth/seaglide_light_on;true;true;7 +event:/sub/seamoth/seaglide_light_off;true;true;30 +event:/sub/seamoth/seaglide_light_on;true;true;30 event:/sub/seamoth/seaglide_loop_rpm;false;false;60 event:/sub/seamoth/seaglide_rev_up;false;false;60 -event:/sub/seamoth/seamoth_light_off;true;true;10 -event:/sub/seamoth/seamoth_light_on;true;true;10 +event:/sub/seamoth/seamoth_light_off;false;false;30 +event:/sub/seamoth/seamoth_light_on;false;false;30 event:/sub/seamoth/seamoth_loop_rpm;false;false;90 event:/sub/seamoth/seamoth_rev_up;false;false;75 event:/sub/seamoth/seamoth_stop;false;false;0 @@ -752,8 +752,8 @@ event:/tools/flare/on_loop;false;false;20 event:/tools/flare/throw;false;false;20 event:/tools/flashlight/deploy;false;false;20 event:/tools/flashlight/fist_use;false;false;20 -event:/tools/flashlight/turn_off;false;false;20 -event:/tools/flashlight/turn_on;false;false;20 +event:/tools/flashlight/turn_off;false;false;30 +event:/tools/flashlight/turn_on;false;false;30 event:/tools/floating_locker/close;false;false;20 event:/tools/floating_locker/deploy;false;false;20 event:/tools/floating_locker/open;false;false;20 @@ -814,4 +814,4 @@ event:/tools/transfuser/take_sample;false;false;0 event:/tools/use_loot;false;false;0 event:/tools/welder/deploy;false;false;20 event:/tools/welder/first_use;false;false;20 -event:/tools/welder/weld_loop;true;false;20 \ No newline at end of file +event:/tools/welder/weld_loop;false;false;0 diff --git a/Nitrox.Assets.Subnautica/classdata.tpk b/Nitrox.Assets.Subnautica/Resources/classdata.tpk similarity index 100% rename from Nitrox.Assets.Subnautica/classdata.tpk rename to Nitrox.Assets.Subnautica/Resources/classdata.tpk diff --git a/Nitrox.BuildTool/Nitrox.BuildTool.csproj b/Nitrox.BuildTool/Nitrox.BuildTool.csproj index e60938f069..da0856686f 100644 --- a/Nitrox.BuildTool/Nitrox.BuildTool.csproj +++ b/Nitrox.BuildTool/Nitrox.BuildTool.csproj @@ -6,14 +6,15 @@ disable bin\ false + Debug;Release;BelowZero;Subnautica - + - + diff --git a/Nitrox.BuildTool/Program.cs b/Nitrox.BuildTool/Program.cs index 07e728cff0..2b622575d3 100644 --- a/Nitrox.BuildTool/Program.cs +++ b/Nitrox.BuildTool/Program.cs @@ -1,4 +1,4 @@ -using System; +using System; using System.Diagnostics; using System.IO; using System.Reflection; @@ -22,7 +22,11 @@ public static class Program public static string GeneratedOutputDir => Path.Combine(ProcessDir, "generated_files"); +#if BELOWZERO + private const int LEGACY_BRANCH_SUBNAUTICA_VERSION = 49370; +#elif SUBNAUTICA private const int LEGACY_BRANCH_SUBNAUTICA_VERSION = 68598; +#endif public static async Task Main(string[] args) { @@ -58,7 +62,11 @@ private static void LogError(string message) private static void AbortIfInvalidGameVersion(GameInstallData game) { +#if BELOWZERO + string gameVersionFile = Path.Combine(game.InstallDir, "SubnauticaZero_Data", "StreamingAssets", "SNUnmanagedData", "plastic_status.ignore"); +#elif SUBNAUTICA string gameVersionFile = Path.Combine(game.InstallDir, "Subnautica_Data", "StreamingAssets", "SNUnmanagedData", "plastic_status.ignore"); +#endif if (!File.Exists(gameVersionFile)) { return; diff --git a/Nitrox.Test/Client/Communication/DeferredPacketReceiverTest.cs b/Nitrox.Test/Client/Communication/DeferredPacketReceiverTest.cs index e7ee7cc735..85db11f35f 100644 --- a/Nitrox.Test/Client/Communication/DeferredPacketReceiverTest.cs +++ b/Nitrox.Test/Client/Communication/DeferredPacketReceiverTest.cs @@ -1,61 +1,42 @@ -using System.Collections.Generic; -using Microsoft.VisualStudio.TestTools.UnitTesting; -using Nitrox.Test; +using Microsoft.VisualStudio.TestTools.UnitTesting; using Nitrox.Test.Client.Communication; using NitroxClient.Map; -using NitroxModel.Core; using NitroxModel.DataStructures.GameLogic; using NitroxModel.DataStructures.Unity; using NitroxModel.Packets; -namespace NitroxClient.Communication -{ - [TestClass] - public class DeferredPacketReceiverTest - { - private readonly VisibleCells visibleCells = new VisibleCells(); - private PacketReceiver packetReceiver; - - // Test Data - private const ushort PLAYER_ID = 1; - private const int CELL_LEVEL = 3; - private readonly NitroxVector3 loadedActionPosition = new NitroxVector3(50, 50, 50); - private readonly NitroxVector3 unloadedActionPosition = new NitroxVector3(200, 200, 200); - private AbsoluteEntityCell loadedCell; - private AbsoluteEntityCell unloadedCell; - private Int3 cellId = Int3.zero; - - [TestInitialize] - public void TestInitialize() - { - NitroxServiceLocator.InitializeDependencyContainer(new ClientAutoFacRegistrar(), new TestAutoFacRegistrar()); - NitroxServiceLocator.BeginNewLifetimeScope(); - - packetReceiver = NitroxServiceLocator.LocateService(); - - loadedCell = new AbsoluteEntityCell(loadedActionPosition, CELL_LEVEL); - unloadedCell = new AbsoluteEntityCell(unloadedActionPosition, CELL_LEVEL); +namespace NitroxClient.Communication; - visibleCells.Add(loadedCell); - } - - [TestMethod] - public void NonActionPacket() - { - TestNonActionPacket packet = new TestNonActionPacket(PLAYER_ID); - packetReceiver.PacketReceived(packet); +[TestClass] +public class DeferredPacketReceiverTest +{ + private readonly VisibleCells visibleCells = new(); + private PacketReceiver packetReceiver; - Queue packets = packetReceiver.GetReceivedPackets(); + // Test Data + private const ushort PLAYER_ID = 1; + private const int CELL_LEVEL = 3; + private readonly NitroxVector3 loadedActionPosition = new(50, 50, 50); + private AbsoluteEntityCell loadedCell; - Assert.AreEqual(1, packets.Count); - Assert.AreEqual(packet, packets.Dequeue()); - Assert.AreEqual(packet.PlayerId, PLAYER_ID); - } + [TestInitialize] + public void TestInitialize() + { + packetReceiver = new PacketReceiver(); + loadedCell = new AbsoluteEntityCell(loadedActionPosition, CELL_LEVEL); + visibleCells.Add(loadedCell); + } - [TestCleanup] - public void Cleanup() - { - NitroxServiceLocator.EndCurrentLifetimeScope(); - } + [TestMethod] + public void NonActionPacket() + { + TestNonActionPacket packet = new(PLAYER_ID); + packetReceiver.Add(packet); + + Packet storedPacket = packetReceiver.GetNextPacket(); + Assert.IsNotNull(storedPacket); + Assert.IsNull(packetReceiver.GetNextPacket()); + Assert.AreEqual(packet, storedPacket); + Assert.AreEqual(packet.PlayerId, PLAYER_ID); } } diff --git a/Nitrox.Test/Client/Communication/PacketSuppressorTest.cs b/Nitrox.Test/Client/Communication/PacketSuppressorTest.cs new file mode 100644 index 0000000000..25c62d5fb3 --- /dev/null +++ b/Nitrox.Test/Client/Communication/PacketSuppressorTest.cs @@ -0,0 +1,53 @@ +using Microsoft.VisualStudio.TestTools.UnitTesting; +using NitroxModel.Packets; + +namespace NitroxClient.Communication; + +[TestClass] +public class PacketSuppressorTest +{ + [TestMethod] + public void SingleSuppress() + { + Assert.IsFalse(PacketSuppressor.IsSuppressed); + Assert.IsFalse(PacketSuppressor.IsSuppressed); + + using (PacketSuppressor.Suppress()) + { + Assert.IsTrue(PacketSuppressor.IsSuppressed); + Assert.IsFalse(PacketSuppressor.IsSuppressed); + } + + Assert.IsFalse(PacketSuppressor.IsSuppressed); + Assert.IsFalse(PacketSuppressor.IsSuppressed); + } + + [TestMethod] + public void MultipleSuppress() + { + Assert.IsFalse(PacketSuppressor.IsSuppressed); + Assert.IsFalse(PacketSuppressor.IsSuppressed); + Assert.IsFalse(PacketSuppressor.IsSuppressed); + Assert.IsFalse(PacketSuppressor.IsSuppressed); + Assert.IsFalse(PacketSuppressor.IsSuppressed); + Assert.IsFalse(PacketSuppressor.IsSuppressed); + + using (PacketSuppressor.Suppress()) + { + Assert.IsFalse(PacketSuppressor.IsSuppressed); + + Assert.IsTrue(PacketSuppressor.IsSuppressed); + Assert.IsTrue(PacketSuppressor.IsSuppressed); + Assert.IsTrue(PacketSuppressor.IsSuppressed); + Assert.IsTrue(PacketSuppressor.IsSuppressed); + Assert.IsTrue(PacketSuppressor.IsSuppressed); + } + + Assert.IsFalse(PacketSuppressor.IsSuppressed); + Assert.IsFalse(PacketSuppressor.IsSuppressed); + Assert.IsFalse(PacketSuppressor.IsSuppressed); + Assert.IsFalse(PacketSuppressor.IsSuppressed); + Assert.IsFalse(PacketSuppressor.IsSuppressed); + Assert.IsFalse(PacketSuppressor.IsSuppressed); + } +} diff --git a/Nitrox.Test/Client/GameLogic/Helper/BaseSerializationHelperTest.cs b/Nitrox.Test/Client/GameLogic/Helper/BaseSerializationHelperTest.cs new file mode 100644 index 0000000000..dcfa71538e --- /dev/null +++ b/Nitrox.Test/Client/GameLogic/Helper/BaseSerializationHelperTest.cs @@ -0,0 +1,85 @@ +using Microsoft.VisualStudio.TestTools.UnitTesting; +using NitroxModel.Logger; +using System; +using System.Collections.Generic; +using System.Linq; + +namespace NitroxClient.GameLogic.Helper; + +[TestClass] +public class BaseSerializationHelperTest +{ + [TestMethod] + public void TestBytesRestoring() + { + List lengths = new() { 10000, 100000, 300000, 500000 }; + foreach (int length in lengths) + { + TestSerialization(GenerateRealisticBytes(length)); + } + } + + [TestMethod] + public void TestAllZeroBytes() + { + List lengths = new() { 10000, 100000, 300000, 500000 }; + foreach (int length in lengths) + { + byte[] data = new byte[length]; + TestSerialization(data); + } + } + + [TestMethod] + public void TestAllMaxBytes() + { + List lengths = new() { 10000, 100000, 300000, 500000 }; + foreach (int length in lengths) + { + byte[] data = new byte[length]; + data.AsSpan().Fill(byte.MaxValue); + TestSerialization(data); + } + } + + /// + /// Generates bytes to emulate Base data arrays + /// + private static byte[] GenerateRealisticBytes(int length) + { + byte[] generated = new byte[length]; + byte[] randomBytes = new byte[length]; + int randomIndex = 0; + Random random = new(); + random.NextBytes(randomBytes); + for (int i = 0; i < length; i++) + { + if (random.Next(100) < 3) + { + generated[i] = randomBytes[randomIndex++]; + } + else + { + generated[i] = 0; + } + } + + return generated; + } + + private static void TestSerialization(byte[] original) + { + byte[] compressed = BaseSerializationHelper.CompressBytes(original); + byte[] decompressed = BaseSerializationHelper.DecompressBytes(compressed, original.Length); + Log.Info($"Size: [Original: {original.Length}, Compressed: {compressed.Length}, Decompressed: {decompressed.Length}]"); + Log.Info($"Original: {string.Join(", ", original.Take(100))}"); + Log.Info($"Compressed: {string.Join(", ", compressed.Take(100))}"); + Log.Info($"Decompressed: {string.Join(", ", decompressed.Take(100))}\n"); + + Assert.AreEqual(original.Length, decompressed.Length); + for (int i = 0; i < original.Length; i++) + { + Assert.AreEqual(original[i], decompressed[i]); + } + } +} diff --git a/Nitrox.Test/GlobalUsings.cs b/Nitrox.Test/GlobalUsings.cs new file mode 100644 index 0000000000..1761e19636 --- /dev/null +++ b/Nitrox.Test/GlobalUsings.cs @@ -0,0 +1,10 @@ +global using static FluentAssertions.FluentActions; +global using FluentAssertions; +global using Microsoft.VisualStudio.TestTools.UnitTesting; +global using System; +global using System.Collections; +global using System.Collections.Generic; +global using System.IO; +global using System.Linq; +global using System.Reflection; +global using System.Threading; diff --git a/Nitrox.Test/Helper/Faker/NitroxAutoFaker.cs b/Nitrox.Test/Helper/Faker/NitroxAutoFaker.cs index 510df23750..6507060e44 100644 --- a/Nitrox.Test/Helper/Faker/NitroxAutoFaker.cs +++ b/Nitrox.Test/Helper/Faker/NitroxAutoFaker.cs @@ -4,7 +4,9 @@ using System.Linq; using System.Reflection; using System.Runtime.Serialization; +using System.Text.RegularExpressions; using BinaryPack.Attributes; +using NitroxModel.Logger; namespace Nitrox.Test.Helper.Faker; @@ -178,10 +180,22 @@ public object GenerateUnsafe(HashSet typeTree) throw new ArgumentOutOfRangeException(); } } - else + else if(propertyInfo.CanWrite) { propertyInfo.SetValue(obj, parameterValues[index]); } + else + { + Regex backingFieldNameRegex = new($"\\A<{propertyInfo.Name}>k__BackingField\\Z"); + FieldInfo backingField = propertyInfo.DeclaringType.GetRuntimeFields().FirstOrDefault(a => backingFieldNameRegex.IsMatch(a.Name)); + + if (backingField == null) + { + throw new InvalidOperationException($"{propertyInfo.DeclaringType}.{propertyInfo.Name} is not accessible for writing"); + } + + backingField.SetValue(obj, parameterValues[index]); + } break; default: diff --git a/Nitrox.Test/Helper/TypeExtension.cs b/Nitrox.Test/Helper/TypeExtension.cs new file mode 100644 index 0000000000..660935a260 --- /dev/null +++ b/Nitrox.Test/Helper/TypeExtension.cs @@ -0,0 +1,22 @@ +using System; + +namespace Nitrox.Test.Helper; + +public static class TypeExtension +{ + public static bool IsAssignableToGenericType(this Type givenType, Type genericType) + { + if (givenType.IsGenericType && givenType.GetGenericTypeDefinition() == genericType) + { + return true; + } + + Type givenBaseType = givenType.BaseType; + if (givenBaseType == null) + { + return false; + } + + return IsAssignableToGenericType(givenBaseType, genericType); + } +} diff --git a/Nitrox.Test/Model/DataStructures/CircularBufferTest.cs b/Nitrox.Test/Model/DataStructures/CircularBufferTest.cs new file mode 100644 index 0000000000..380e877303 --- /dev/null +++ b/Nitrox.Test/Model/DataStructures/CircularBufferTest.cs @@ -0,0 +1,117 @@ +using FluentAssertions; +using Microsoft.VisualStudio.TestTools.UnitTesting; + +namespace NitroxModel.DataStructures; + +[TestClass] +public class CircularBufferTest +{ + [TestMethod] + public void ShouldLimitSizeToMaxSize() + { + CircularBuffer buffer = new(1); + buffer.Count.Should().Be(0); + buffer.Add("1"); + buffer.Count.Should().Be(1); + buffer.Add("2"); + buffer.Count.Should().Be(1); + + buffer = new CircularBuffer(5); + buffer.Count.Should().Be(0); + buffer.Add("1"); + buffer.Count.Should().Be(1); + buffer.Add("2"); + buffer.Count.Should().Be(2); + buffer.Add("3"); + buffer.Count.Should().Be(3); + buffer.Add("4"); + buffer.Count.Should().Be(4); + buffer.Add("5"); + buffer.Count.Should().Be(5); + buffer.Add("6"); + buffer.Count.Should().Be(5); + } + + [TestMethod] + public void ShouldOverwriteOldestItemInBufferWhenCapped() + { + CircularBuffer buffer = new(3); + buffer.Add("1"); + buffer[0].Should().Be("1"); + buffer.Add("2"); + buffer[1].Should().Be("2"); + buffer.Add("3"); + buffer[2].Should().Be("3"); + buffer.Add("4"); + buffer[0].Should().Be("4"); + buffer.Add("5"); + buffer[1].Should().Be("5"); + buffer[2].Should().Be("3"); + buffer.Add("6"); + buffer[2].Should().Be("6"); + buffer.Add("7"); + buffer.Should().ContainInOrder("7", "5", "6"); + } + + [TestMethod] + public void ShouldDiscardAddIfCapacityReached() + { + CircularBuffer buffer = new(0); + buffer.Count.Should().Be(0); + buffer.Add("1"); + buffer.Count.Should().Be(0); + } + + [TestMethod] + public void ShouldBeEmptyWhenCleared() + { + CircularBuffer buffer = new(10); + buffer.Count.Should().Be(0); + buffer.Add("1"); + buffer.Add("1"); + buffer.Add("1"); + buffer.Count.Should().Be(3); + buffer.Clear(); + buffer.Count.Should().Be(0); + } + + [TestMethod] + public void ShouldGiveLastChanged() + { + CircularBuffer buffer = new(3); + buffer.LastChangedIndex.Should().Be(-1); + buffer.Add(1); + buffer.LastChangedIndex.Should().Be(0); + buffer.Add(2); + buffer.LastChangedIndex.Should().Be(1); + buffer.Add(3); + buffer.LastChangedIndex.Should().Be(2); + buffer.Add(4); + buffer.LastChangedIndex.Should().Be(0); + buffer.Add(5); + buffer.LastChangedIndex.Should().Be(1); + buffer.Add(6); + buffer.LastChangedIndex.Should().Be(2); + buffer.Add(7); + buffer.LastChangedIndex.Should().Be(0); + buffer.Add(8); + buffer.LastChangedIndex.Should().Be(1); + buffer.Clear(); + buffer.LastChangedIndex.Should().Be(-1); + } + + [TestMethod] + public void ShouldReverseOrderWithNegativeIndex() + { + CircularBuffer buffer = new(6); + buffer.AddRange(1, 2, 3, 4, 5, 6); + buffer[-1].Should().Be(6); + buffer[-2].Should().Be(5); + buffer[-3].Should().Be(4); + buffer[-4].Should().Be(3); + buffer[-5].Should().Be(2); + buffer[-6].Should().Be(1); + buffer[-7].Should().Be(6); + buffer[-8].Should().Be(5); + } +} diff --git a/Nitrox.Test/Model/ExtensionsTests.cs b/Nitrox.Test/Model/ExtensionsTests.cs index 327b78176b..69ffd186e9 100644 --- a/Nitrox.Test/Model/ExtensionsTests.cs +++ b/Nitrox.Test/Model/ExtensionsTests.cs @@ -1,9 +1,4 @@ -using System; -using System.Collections.Generic; -using FluentAssertions; -using Microsoft.VisualStudio.TestTools.UnitTesting; - -namespace NitroxModel; +namespace NitroxModel; [TestClass] public class ExtensionsTest @@ -71,4 +66,35 @@ public void RemoveAllFast_CanRemoveItemsWithExtraParameterInPredicate() list.RemoveAllFast(3, static (item, length) => item.Length == length); list.Should().BeEquivalentTo("three", "four"); } + + [TestMethod] + public void GetUniqueNonCombinatoryFlags_ShouldReturnUniqueNonCombinatoryFlags() + { + TestEnumFlags.ALL.GetUniqueNonCombinatoryFlags().Should().BeEquivalentTo([TestEnumFlags.A, TestEnumFlags.B, TestEnumFlags.C, TestEnumFlags.D, TestEnumFlags.E, TestEnumFlags.F]); + TestEnumFlags.CDEF.GetUniqueNonCombinatoryFlags().Should().BeEquivalentTo([TestEnumFlags.C, TestEnumFlags.D, TestEnumFlags.E, TestEnumFlags.F]); + TestEnumFlags.E.GetUniqueNonCombinatoryFlags().Should().BeEquivalentTo([TestEnumFlags.E]); + TestEnumFlags.NONE.GetUniqueNonCombinatoryFlags().Should().BeEmpty(); + } + + [TestMethod] + public void GetUniqueNonCombinatorFlags_ShouldReturnAllUniquesWhenAllBitsSet() + { + ((TestEnumFlags)int.MaxValue).GetUniqueNonCombinatoryFlags().Should().BeEquivalentTo([TestEnumFlags.A, TestEnumFlags.B, TestEnumFlags.C, TestEnumFlags.D, TestEnumFlags.E, TestEnumFlags.F]); + } + + [Flags] + private enum TestEnumFlags + { + NONE = 0, + F = 1 << 5, + A = 1 << 0, + B = 1 << 1, + C = 1 << 2, + D = 1 << 3, + E = 1 << 4, + AB = A | B, + CD = C | D, + CDEF = CD | E | F, + ALL = AB | CDEF + } } diff --git a/Nitrox.Test/Model/Helper/NetHelperTest.cs b/Nitrox.Test/Model/Helper/NetHelperTest.cs index affa337892..ef60de9fa6 100644 --- a/Nitrox.Test/Model/Helper/NetHelperTest.cs +++ b/Nitrox.Test/Model/Helper/NetHelperTest.cs @@ -1,4 +1,6 @@ -using System.Net; +using System; +using System.Net; +using System.Net.Sockets; using FluentAssertions; using Microsoft.VisualStudio.TestTools.UnitTesting; @@ -11,11 +13,11 @@ public class NetHelperTest public void ShouldMatchPrivateIps() { // Tested subnet ranges that are reserved for private networks: - // 10.0.0.0/8 - // 127.0.0.0/8 - // 172.16.0.0/12 - // 192.0.0.0/24 - // 192.168.0.0/16 + // 10.0.0.0/8 + // 127.0.0.0/8 + // 172.16.0.0/12 + // 192.0.0.0/24 + // 192.168.0.0/16 // 198.18.0.0/15 IPAddress.Parse("10.0.0.0").IsPrivate().Should().BeTrue(); @@ -36,4 +38,34 @@ public void ShouldMatchPrivateIps() IPAddress.Parse("198.17.255.255").IsPrivate().Should().BeFalse(); IPAddress.Parse("198.20.0.0").IsPrivate().Should().BeFalse(); } + + [TestMethod] + public void ShouldMatchLocalhostIps() + { + IPAddress GetSlightlyDifferentIp(IPAddress address) + { + if (address.AddressFamily != AddressFamily.InterNetwork) + { + throw new Exception("Only supports IPv4"); + } + byte[] bytes = address.GetAddressBytes(); + unchecked + { + while (bytes[3] is < 1 or > 253) + { + bytes[3]++; + } + bytes[3]++; + } + return new IPAddress(bytes); + } + + IPAddress.Parse("127.0.0.1").IsLocalhost().Should().BeTrue(); + IPAddress.Parse("127.0.0.2").IsLocalhost().Should().BeTrue(); + IPAddress.Parse("192.168.0.255").IsLocalhost().Should().BeFalse(); + NetHelper.GetLanIp().IsLocalhost().Should().BeTrue(); + IPAddress differentIp = GetSlightlyDifferentIp(NetHelper.GetLanIp()); + differentIp.Should().NotBeEquivalentTo(NetHelper.GetLanIp()); + differentIp.IsLocalhost().Should().BeFalse(); + } } diff --git a/Nitrox.Test/Model/Packets/Processors/PacketProcessorTest.cs b/Nitrox.Test/Model/Packets/Processors/PacketProcessorTest.cs index 13ee077662..773e6d9b2c 100644 --- a/Nitrox.Test/Model/Packets/Processors/PacketProcessorTest.cs +++ b/Nitrox.Test/Model/Packets/Processors/PacketProcessorTest.cs @@ -1,12 +1,10 @@ using System; using System.Collections.Generic; using System.Linq; -using FluentAssertions; using Microsoft.VisualStudio.TestTools.UnitTesting; using Nitrox.Test; using NitroxClient; using NitroxClient.Communication.Packets.Processors.Abstract; -using NitroxClient.MonoBehaviours; using NitroxModel.Core; using NitroxModel.Packets.Processors.Abstract; using NitroxServer; @@ -23,91 +21,91 @@ public class PacketProcessorTest [TestMethod] public void ClientPacketProcessorSanity() { - typeof(Multiplayer).Assembly.GetTypes() - .Where(p => typeof(PacketProcessor).IsAssignableFrom(p) && p.IsClass && !p.IsAbstract) - .ToList() - .ForEach(processor => - { - // Make sure that each packetprocessor is derived from the ClientPacketProcessor class, - // so that it's packet-type can be determined. - Assert.IsTrue(processor.BaseType.IsGenericType, $"{processor} does not derive from a generic type!"); - Assert.IsTrue(processor.BaseType.GetGenericTypeDefinition() == typeof(ClientPacketProcessor<>), $"{processor} does not derive from ClientPacketProcessor!"); + typeof(ClientPacketProcessor<>).Assembly.GetTypes() + .Where(p => typeof(PacketProcessor).IsAssignableFrom(p) && p.IsClass && !p.IsAbstract) + .ToList() + .ForEach(processor => + { + // Make sure that each packet-processor is derived from the ClientPacketProcessor class, + // so that it's packet-type can be determined. + Assert.IsNotNull(processor.BaseType, $"{processor} does not derive from any type!"); + Assert.IsTrue(processor.BaseType.IsGenericType, $"{processor} does not derive from a generic type!"); + Assert.IsTrue(processor.BaseType.IsAssignableToGenericType(typeof(ClientPacketProcessor<>)), $"{processor} does not derive from ClientPacketProcessor!"); - // Check constructor availability: - int numCtors = processor.GetConstructors().Length; - Assert.IsTrue(numCtors == 1, $"{processor} should have exactly 1 constructor! (has {numCtors})"); - }); + // Check constructor availability: + int numCtors = processor.GetConstructors().Length; + Assert.IsTrue(numCtors == 1, $"{processor} should have exactly 1 constructor! (has {numCtors})"); + }); } [TestMethod] public void ServerPacketProcessorSanity() { typeof(PacketHandler).Assembly.GetTypes() - .Where(p => typeof(PacketProcessor).IsAssignableFrom(p) && p.IsClass && !p.IsAbstract) - .ToList() - .ForEach(processor => - { - // Make sure that each packetprocessor is derived from the ClientPacketProcessor class, - // so that it's packet-type can be determined. - Assert.IsTrue(processor.BaseType.IsGenericType, $"{processor} does not derive from a generic type!"); - Type baseGenericType = processor.BaseType.GetGenericTypeDefinition(); - Assert.IsTrue(baseGenericType == typeof(AuthenticatedPacketProcessor<>) || baseGenericType == typeof(UnauthenticatedPacketProcessor<>), $"{processor} does not derive from (Un)AuthenticatedPacketProcessor!"); + .Where(p => typeof(PacketProcessor).IsAssignableFrom(p) && p.IsClass && !p.IsAbstract) + .ToList() + .ForEach(processor => + { + // Make sure that each packet-processor is derived from the ClientPacketProcessor class, + // so that it's packet-type can be determined. + Assert.IsNotNull(processor.BaseType, $"{processor} does not derive from any type!"); + Assert.IsTrue(processor.BaseType.IsGenericType, $"{processor} does not derive from a generic type!"); + Assert.IsTrue(processor.BaseType.IsAssignableToGenericType(typeof(AuthenticatedPacketProcessor<>)) || + processor.BaseType.IsAssignableToGenericType(typeof(UnauthenticatedPacketProcessor<>)), $"{processor} does not derive from (Un)AuthenticatedPacketProcessor!"); - // Check constructor availability: - int numCtors = processor.GetConstructors().Length; - Assert.IsTrue(numCtors == 1, $"{processor} should have exactly 1 constructor! (has {numCtors})"); + // Check constructor availability: + int numCtors = processor.GetConstructors().Length; + Assert.IsTrue(numCtors == 1, $"{processor} should have exactly 1 constructor! (has {numCtors})"); - // Unable to check parameters, these are defined in PacketHandler.ctor - }); + // Unable to check parameters, these are defined in PacketHandler.ctor + }); } [TestMethod] public void SameAmountOfServerPacketProcessors() { IEnumerable processors = typeof(PacketHandler).Assembly.GetTypes() - .Where(p => typeof(PacketProcessor).IsAssignableFrom(p) && p.IsClass && !p.IsAbstract); + .Where(p => typeof(PacketProcessor).IsAssignableFrom(p) && p.IsClass && !p.IsAbstract); ServerAutoFacRegistrar serverDependencyRegistrar = new ServerAutoFacRegistrar(); NitroxServiceLocator.InitializeDependencyContainer(serverDependencyRegistrar); NitroxServiceLocator.BeginNewLifetimeScope(); List packetTypes = typeof(DefaultServerPacketProcessor).Assembly.GetTypes() - .Where(p => typeof(PacketProcessor).IsAssignableFrom(p) && p.IsClass && !p.IsAbstract) - .ToList(); + .Where(p => typeof(PacketProcessor).IsAssignableFrom(p) && p.IsClass && !p.IsAbstract) + .ToList(); int both = packetTypes.Count; - Assert.AreEqual(processors.Count(), - both, - $"Not all(Un) AuthenticatedPacketProcessors have been discovered by the runtime code (auth + unauth: {both} out of {processors.Count()}). Perhaps the runtime matching code is too strict, or a processor does not derive from ClientPacketProcessor (and will hence not be detected)."); + Assert.AreEqual(processors.Count(), both, + $"Not all(Un) AuthenticatedPacketProcessors have been discovered by the runtime code (auth + unauth: {both} out of {processors.Count()}). Perhaps the runtime matching code is too strict, or a processor does not derive from ClientPacketProcessor (and will hence not be detected)."); } [TestMethod] public void AllPacketsAreHandled() { List packetTypes = typeof(DefaultServerPacketProcessor).Assembly.GetTypes() - .Where(p => typeof(PacketProcessor).IsAssignableFrom(p) && p.IsClass && !p.IsAbstract) - .ToList(); + .Where(p => typeof(PacketProcessor).IsAssignableFrom(p) && p.IsClass && !p.IsAbstract) + .ToList(); + + List abstractProcessorTypes = new(); + + abstractProcessorTypes.AddRange(typeof(ClientPacketProcessor<>) + .Assembly.GetTypes() + .Where(p => p.IsClass && p.IsAbstract && p.IsAssignableToGenericType(typeof(ClientPacketProcessor<>)))); + + abstractProcessorTypes.AddRange(typeof(AuthenticatedPacketProcessor<>) + .Assembly.GetTypes() + .Where(p => p.IsClass && p.IsAbstract && (p.IsAssignableToGenericType(typeof(AuthenticatedPacketProcessor<>)) || p.IsAssignableToGenericType(typeof(UnauthenticatedPacketProcessor<>))))); NitroxServiceLocator.InitializeDependencyContainer(new ClientAutoFacRegistrar(), new SubnauticaServerAutoFacRegistrar(), new TestAutoFacRegistrar()); NitroxServiceLocator.BeginNewLifetimeScope(); - foreach (Type packet in typeof(Packet).Assembly.GetTypes() - .Where(p => typeof(Packet).IsAssignableFrom(p) && p.IsClass && !p.IsAbstract) - .ToList()) + foreach (Type packet in typeof(Packet).Assembly.GetTypes().Where(p => typeof(Packet).IsAssignableFrom(p) && p.IsClass && !p.IsAbstract).ToList()) { - Type clientPacketProcessorType = typeof(ClientPacketProcessor<>); - Type authenticatedPacketProcessorType = typeof(AuthenticatedPacketProcessor<>); - Type unauthenticatedPacketProcessorType = typeof(UnauthenticatedPacketProcessor<>); - - Type clientProcessorType = clientPacketProcessorType.MakeGenericType(packet); - Type authProcessorType = authenticatedPacketProcessorType.MakeGenericType(packet); - Type unauthProcessorType = unauthenticatedPacketProcessorType.MakeGenericType(packet); - - Console.WriteLine($@"Checking handler for packet {packet}..."); - (packetTypes.Contains(packet) || - NitroxServiceLocator.LocateOptionalService(clientProcessorType).HasValue || - NitroxServiceLocator.LocateOptionalService(authProcessorType).HasValue || - NitroxServiceLocator.LocateOptionalService(unauthProcessorType).HasValue).Should() - .BeTrue($"Packet of type '{packet}' should have at least one processor."); + Assert.IsTrue(packetTypes.Contains(packet) || abstractProcessorTypes.Any(genericProcessor => + { + Type processorType = genericProcessor.MakeGenericType(packet); + return NitroxServiceLocator.LocateOptionalService(processorType).HasValue; + }), $"Packet of type '{packet}' should have at least one processor."); } } diff --git a/Nitrox.Test/Nitrox.Test.csproj b/Nitrox.Test/Nitrox.Test.csproj index 7e032ebeec..f5ad312f7d 100644 --- a/Nitrox.Test/Nitrox.Test.csproj +++ b/Nitrox.Test/Nitrox.Test.csproj @@ -1,17 +1,18 @@ - + net472 disable false + Debug;Release;BelowZero;Subnautica - - + + @@ -30,15 +31,15 @@ - + - + - + - + diff --git a/Nitrox.Test/Patcher/PatchTestHelper.cs b/Nitrox.Test/Patcher/PatchTestHelper.cs index 2923eb8f3c..04035e83ea 100644 --- a/Nitrox.Test/Patcher/PatchTestHelper.cs +++ b/Nitrox.Test/Patcher/PatchTestHelper.cs @@ -52,7 +52,7 @@ public static ILGenerator GetILGenerator(this MethodInfo method) public static void TestPattern(MethodInfo targetMethod, InstructionsPattern pattern, out IEnumerable originalIl, out IEnumerable transformedIl) { bool shouldHappen = false; - originalIl = GetInstructionsFromMethod(targetMethod); + originalIl = PatchProcessor.GetCurrentInstructions(targetMethod); transformedIl = originalIl .Transform(pattern, (_, _) => { diff --git a/Nitrox.Test/Patcher/Patches/Dynamic/BaseDeconstructable_Deconstruct_PatchTest.cs b/Nitrox.Test/Patcher/Patches/Dynamic/BaseDeconstructable_Deconstruct_PatchTest.cs new file mode 100644 index 0000000000..9ca1f81e7a --- /dev/null +++ b/Nitrox.Test/Patcher/Patches/Dynamic/BaseDeconstructable_Deconstruct_PatchTest.cs @@ -0,0 +1,20 @@ +using System.Collections.Generic; +using System.Linq; +using FluentAssertions; +using HarmonyLib; +using Microsoft.VisualStudio.TestTools.UnitTesting; +using NitroxTest.Patcher; + +namespace NitroxPatcher.Patches.Dynamic; + +[TestClass] +public class BaseDeconstructable_Deconstruct_PatchTest +{ + [TestMethod] + public void Sanity() + { + IEnumerable originalIl = PatchTestHelper.GetInstructionsFromMethod(BaseDeconstructable_Deconstruct_Patch.TARGET_METHOD); + IEnumerable transformedIl = BaseDeconstructable_Deconstruct_Patch.Transpiler(null, originalIl); + originalIl.Count().Should().Be(transformedIl.Count() - BaseDeconstructable_Deconstruct_Patch.InstructionsToAdd(true).Count() * 2); + } +} diff --git a/Nitrox.Test/Patcher/Patches/Dynamic/BaseGhost_Finish_PatchTest.cs b/Nitrox.Test/Patcher/Patches/Dynamic/BaseGhost_Finish_PatchTest.cs deleted file mode 100644 index 3e86bed676..0000000000 --- a/Nitrox.Test/Patcher/Patches/Dynamic/BaseGhost_Finish_PatchTest.cs +++ /dev/null @@ -1,32 +0,0 @@ -using System.Collections.Generic; -using System.Linq; -using HarmonyLib; -using Microsoft.VisualStudio.TestTools.UnitTesting; -using NitroxTest.Patcher; - -namespace NitroxPatcher.Patches.Dynamic -{ - [TestClass] - public class BaseGhost_Finish_PatchTest - { - [TestMethod] - public void Sanity() - { - List instructions = PatchTestHelper.GenerateDummyInstructions(100); - instructions.Add(new CodeInstruction(BaseGhost_Finish_Patch.INJECTION_OPCODE, BaseGhost_Finish_Patch.INJECTION_OPERAND)); - - IEnumerable result = BaseGhost_Finish_Patch.Transpiler(null, instructions); - - Assert.AreEqual(instructions.Count + 3, result.Count()); - } - - [TestMethod] - public void InjectionSanity() - { - IEnumerable beforeInstructions = PatchTestHelper.GetInstructionsFromMethod(BaseGhost_Finish_Patch.TARGET_METHOD); - IEnumerable result = BaseGhost_Finish_Patch.Transpiler(BaseGhost_Finish_Patch.TARGET_METHOD, beforeInstructions); - - Assert.IsTrue(beforeInstructions.Count() < result.Count()); - } - } -} diff --git a/Nitrox.Test/Patcher/Patches/Dynamic/BaseHullStrength_CrushDamageUpdate_PatchTest.cs b/Nitrox.Test/Patcher/Patches/Dynamic/BaseHullStrength_CrushDamageUpdate_PatchTest.cs new file mode 100644 index 0000000000..bdd57d191d --- /dev/null +++ b/Nitrox.Test/Patcher/Patches/Dynamic/BaseHullStrength_CrushDamageUpdate_PatchTest.cs @@ -0,0 +1,20 @@ +using System.Collections.Generic; +using System.Linq; +using FluentAssertions; +using HarmonyLib; +using Microsoft.VisualStudio.TestTools.UnitTesting; +using NitroxTest.Patcher; + +namespace NitroxPatcher.Patches.Dynamic; + +[TestClass] +public class BaseHullStrength_CrushDamageUpdate_PatchTest +{ + [TestMethod] + public void Sanity() + { + IEnumerable originalIl = PatchTestHelper.GetInstructionsFromMethod(BaseHullStrength_CrushDamageUpdate_Patch.TARGET_METHOD); + IEnumerable transformedIl = BaseHullStrength_CrushDamageUpdate_Patch.Transpiler(originalIl); + transformedIl.Count().Should().Be(originalIl.Count() + 3); + } +} diff --git a/Nitrox.Test/Patcher/Patches/Dynamic/BuilderPatchTest.cs b/Nitrox.Test/Patcher/Patches/Dynamic/BuilderPatchTest.cs deleted file mode 100644 index 1e73820626..0000000000 --- a/Nitrox.Test/Patcher/Patches/Dynamic/BuilderPatchTest.cs +++ /dev/null @@ -1,36 +0,0 @@ -using System.Collections.Generic; -using System.Collections.ObjectModel; -using System.Linq; -using System.Reflection; -using HarmonyLib; -using Microsoft.VisualStudio.TestTools.UnitTesting; -using NitroxModel.Helper; -using NitroxTest.Patcher; - -namespace NitroxPatcher.Patches.Dynamic -{ - [TestClass] - public class BuilderPatchTest - { - [TestMethod] - public void Sanity() - { - List instructions = PatchTestHelper.GenerateDummyInstructions(100); - instructions.Add(new CodeInstruction(Builder_TryPlace_Patch.PLACE_BASE_INJECTION_OPCODE, Builder_TryPlace_Patch.PLACE_BASE_INJECTION_OPERAND)); - instructions.Add(new CodeInstruction(Builder_TryPlace_Patch.PLACE_FURNITURE_INJECTION_OPCODE, Builder_TryPlace_Patch.PLACE_FURNITURE_INJECTION_OPERAND)); - - IEnumerable result = Builder_TryPlace_Patch.Transpiler(null, instructions); - Assert.AreEqual(120, result.Count()); - } - - [TestMethod] - public void InjectionSanity() - { - MethodInfo targetMethod = Reflect.Method(() => Builder.TryPlace()); - ReadOnlyCollection beforeInstructions = PatchTestHelper.GetInstructionsFromMethod(targetMethod); - - IEnumerable result = Builder_TryPlace_Patch.Transpiler(targetMethod, beforeInstructions); - Assert.IsTrue(beforeInstructions.Count < result.Count()); - } - } -} diff --git a/Nitrox.Test/Patcher/Patches/Dynamic/BuilderTool_HandleInput_PatchTest.cs b/Nitrox.Test/Patcher/Patches/Dynamic/BuilderTool_HandleInput_PatchTest.cs deleted file mode 100644 index 6a8ae10f7a..0000000000 --- a/Nitrox.Test/Patcher/Patches/Dynamic/BuilderTool_HandleInput_PatchTest.cs +++ /dev/null @@ -1,33 +0,0 @@ -using System.Collections.Generic; -using System.Collections.ObjectModel; -using System.Linq; -using HarmonyLib; -using Microsoft.VisualStudio.TestTools.UnitTesting; -using NitroxTest.Patcher; - -namespace NitroxPatcher.Patches.Dynamic -{ - [TestClass] - public class BuilderTool_HandleInput_PatchTest - { - [TestMethod] - public void Sanity() - { - List instructions = PatchTestHelper.GenerateDummyInstructions(100); - instructions.Add(new CodeInstruction(BuilderTool_HandleInput_Patch.INJECTION_OPCODE, BuilderTool_HandleInput_Patch.INJECTION_OPERAND)); - - IEnumerable result = BuilderTool_HandleInput_Patch.Transpiler(BuilderTool_HandleInput_Patch.TARGET_METHOD, instructions); - - Assert.AreEqual(instructions.Count + 5, result.Count()); - } - - [TestMethod] - public void InjectionSanity() - { - ReadOnlyCollection beforeInstructions = PatchTestHelper.GetInstructionsFromMethod(BuilderTool_HandleInput_Patch.TARGET_METHOD); - IEnumerable result = BuilderTool_HandleInput_Patch.Transpiler(BuilderTool_HandleInput_Patch.TARGET_METHOD, beforeInstructions); - - Assert.IsTrue(beforeInstructions.Count < result.Count()); - } - } -} diff --git a/Nitrox.Test/Patcher/Patches/Dynamic/Builder_TryPlace_PatchTest.cs b/Nitrox.Test/Patcher/Patches/Dynamic/Builder_TryPlace_PatchTest.cs new file mode 100644 index 0000000000..131f80ca27 --- /dev/null +++ b/Nitrox.Test/Patcher/Patches/Dynamic/Builder_TryPlace_PatchTest.cs @@ -0,0 +1,25 @@ +using FluentAssertions; +using HarmonyLib; +using Microsoft.VisualStudio.TestTools.UnitTesting; +using NitroxTest.Patcher; +using System.Collections.Generic; +using System.Linq; + +namespace NitroxPatcher.Patches.Dynamic; + +[TestClass] +public class Builder_TryPlace_PatchTest +{ + [TestMethod] + public void Sanity() + { + IEnumerable originalIl = PatchTestHelper.GetInstructionsFromMethod(Builder_TryPlace_Patch.TARGET_METHOD); +#if SUBNAUTICA + IEnumerable transformedIl = Builder_TryPlace_Patch.Transpiler(null, originalIl); + originalIl.Count().Should().Be(transformedIl.Count() - (Builder_TryPlace_Patch.InstructionsToAdd1.Count + Builder_TryPlace_Patch.InstructionsToAdd2.Count)); +#elif BELOWZERO + IEnumerable transformedIl = Builder_TryPlace_Patch.Transpiler(null, originalIl, Builder_TryPlace_Patch.TARGET_METHOD.GetILGenerator()); + originalIl.Count().Should().Be(transformedIl.Count() - 4); +#endif + } +} diff --git a/Nitrox.Test/Patcher/Patches/Dynamic/ConstructableBase_SetState_PatchTest.cs b/Nitrox.Test/Patcher/Patches/Dynamic/ConstructableBase_SetState_PatchTest.cs index 559e8f66d0..3bc10e0339 100644 --- a/Nitrox.Test/Patcher/Patches/Dynamic/ConstructableBase_SetState_PatchTest.cs +++ b/Nitrox.Test/Patcher/Patches/Dynamic/ConstructableBase_SetState_PatchTest.cs @@ -1,32 +1,20 @@ -using System.Collections.Generic; +using System.Collections.Generic; using System.Linq; +using FluentAssertions; using HarmonyLib; using Microsoft.VisualStudio.TestTools.UnitTesting; using NitroxTest.Patcher; -namespace NitroxPatcher.Patches.Dynamic +namespace NitroxPatcher.Patches.Dynamic; + +[TestClass] +public class ConstructableBase_SetState_PatchTest { - [TestClass] - public class ConstructableBase_SetState_PatchTest + [TestMethod] + public void Sanity() { - [TestMethod] - public void Sanity() - { - List instructions = PatchTestHelper.GenerateDummyInstructions(100); - instructions.Add(new CodeInstruction(ConstructableBase_SetState_Patch.INJECTION_OPCODE, ConstructableBase_SetState_Patch.INJECTION_OPERAND)); - - IEnumerable result = ConstructableBase_SetState_Patch.Transpiler(ConstructableBase_SetState_Patch.TARGET_METHOD, instructions); - - Assert.AreEqual(instructions.Count + 2, result.Count()); - } - - [TestMethod] - public void InjectionSanity() - { - IEnumerable beforeInstructions = PatchTestHelper.GetInstructionsFromMethod(ConstructableBase_SetState_Patch.TARGET_METHOD); - IEnumerable result = ConstructableBase_SetState_Patch.Transpiler(ConstructableBase_SetState_Patch.TARGET_METHOD, beforeInstructions); - - Assert.IsTrue(beforeInstructions.Count() < result.Count()); - } + IEnumerable originalIl = PatchTestHelper.GetInstructionsFromMethod(ConstructableBase_SetState_Patch.TARGET_METHOD); + IEnumerable transformedIl = ConstructableBase_SetState_Patch.Transpiler(null, originalIl); + originalIl.Count().Should().Be(transformedIl.Count() - ConstructableBase_SetState_Patch.InstructionsToAdd.Count); } } diff --git a/Nitrox.Test/Patcher/Patches/Dynamic/Constructable_Construct_PatchTest.cs b/Nitrox.Test/Patcher/Patches/Dynamic/Constructable_Construct_PatchTest.cs new file mode 100644 index 0000000000..250ccf83a4 --- /dev/null +++ b/Nitrox.Test/Patcher/Patches/Dynamic/Constructable_Construct_PatchTest.cs @@ -0,0 +1,20 @@ +using FluentAssertions; +using HarmonyLib; +using Microsoft.VisualStudio.TestTools.UnitTesting; +using NitroxTest.Patcher; +using System.Collections.Generic; +using System.Linq; + +namespace NitroxPatcher.Patches.Dynamic; + +[TestClass] +public class Constructable_Construct_PatchTest +{ + [TestMethod] + public void Sanity() + { + IEnumerable originalIl = PatchTestHelper.GetInstructionsFromMethod(Constructable_Construct_Patch.TARGET_METHOD); + IEnumerable transformedIl = Constructable_Construct_Patch.Transpiler(null, originalIl); + originalIl.Count().Should().Be(transformedIl.Count() - Constructable_Construct_Patch.InstructionsToAdd.Count); + } +} diff --git a/Nitrox.Test/Patcher/Patches/Dynamic/Constructable_DeconstructAsync_PatchTest.cs b/Nitrox.Test/Patcher/Patches/Dynamic/Constructable_DeconstructAsync_PatchTest.cs new file mode 100644 index 0000000000..30d59bbac1 --- /dev/null +++ b/Nitrox.Test/Patcher/Patches/Dynamic/Constructable_DeconstructAsync_PatchTest.cs @@ -0,0 +1,20 @@ +using FluentAssertions; +using HarmonyLib; +using Microsoft.VisualStudio.TestTools.UnitTesting; +using NitroxTest.Patcher; +using System.Collections.Generic; +using System.Linq; + +namespace NitroxPatcher.Patches.Dynamic; + +[TestClass] +public class Constructable_DeconstructAsync_PatchTest +{ + [TestMethod] + public void Sanity() + { + IEnumerable originalIl = PatchTestHelper.GetInstructionsFromMethod(Constructable_DeconstructAsync_Patch.TARGET_METHOD); + IEnumerable transformedIl = Constructable_DeconstructAsync_Patch.Transpiler(null, originalIl); + originalIl.Count().Should().Be(transformedIl.Count() - Constructable_DeconstructAsync_Patch.InstructionsToAdd.Count); + } +} diff --git a/Nitrox.Test/Patcher/Patches/Dynamic/ConstructorInput_OnCraftingBegin_PatchTest.cs b/Nitrox.Test/Patcher/Patches/Dynamic/ConstructorInput_OnCraftingBegin_PatchTest.cs index 117bb50594..22abedb2af 100644 --- a/Nitrox.Test/Patcher/Patches/Dynamic/ConstructorInput_OnCraftingBegin_PatchTest.cs +++ b/Nitrox.Test/Patcher/Patches/Dynamic/ConstructorInput_OnCraftingBegin_PatchTest.cs @@ -1,4 +1,4 @@ -using System.Collections.Generic; +using System.Collections.Generic; using System.Collections.ObjectModel; using System.Linq; using HarmonyLib; @@ -18,7 +18,7 @@ public void Sanity() IEnumerable result = ConstructorInput_OnCraftingBegin_Patch.Transpiler(null, instructions); - Assert.AreEqual(instructions.Count + 3, result.Count()); + Assert.AreEqual(instructions.Count + 7, result.Count()); } [TestMethod] diff --git a/Nitrox.Test/Patcher/Patches/Dynamic/CrashHome_Spawn_PatchTest.cs b/Nitrox.Test/Patcher/Patches/Dynamic/CrashHome_Spawn_PatchTest.cs new file mode 100644 index 0000000000..66beb2618a --- /dev/null +++ b/Nitrox.Test/Patcher/Patches/Dynamic/CrashHome_Spawn_PatchTest.cs @@ -0,0 +1,20 @@ +using System.Collections.Generic; +using System.Linq; +using FluentAssertions; +using HarmonyLib; +using Microsoft.VisualStudio.TestTools.UnitTesting; +using NitroxTest.Patcher; + +namespace NitroxPatcher.Patches.Dynamic; + +[TestClass] +public class CrashHome_Spawn_PatchTest +{ + [TestMethod] + public void Sanity() + { + IEnumerable originalIl = PatchTestHelper.GetInstructionsFromMethod(CrashHome_Spawn_Patch.TARGET_METHOD); + IEnumerable transformedIl = CrashHome_Spawn_Patch.Transpiler(originalIl); + transformedIl.Count().Should().Be(originalIl.Count() + 2); + } +} diff --git a/Nitrox.Test/Patcher/Patches/Dynamic/CrashHome_Update_PatchTest.cs b/Nitrox.Test/Patcher/Patches/Dynamic/CrashHome_Update_PatchTest.cs new file mode 100644 index 0000000000..40963bfd17 --- /dev/null +++ b/Nitrox.Test/Patcher/Patches/Dynamic/CrashHome_Update_PatchTest.cs @@ -0,0 +1,20 @@ +using System.Collections.Generic; +using System.Linq; +using FluentAssertions; +using HarmonyLib; +using Microsoft.VisualStudio.TestTools.UnitTesting; +using NitroxTest.Patcher; + +namespace NitroxPatcher.Patches.Dynamic; + +[TestClass] +public class CrashHome_Update_PatchTest +{ + [TestMethod] + public void Sanity() + { + IEnumerable originalIl = PatchTestHelper.GetInstructionsFromMethod(CrashHome_Update_Patch.TARGET_METHOD); + IEnumerable transformedIl = CrashHome_Update_Patch.Transpiler(originalIl); + transformedIl.Count().Should().Be(originalIl.Count() - 5); + } +} diff --git a/Nitrox.Test/Patcher/Patches/Dynamic/CreatureDeath_OnKillAsync_PatchTest.cs b/Nitrox.Test/Patcher/Patches/Dynamic/CreatureDeath_OnKillAsync_PatchTest.cs new file mode 100644 index 0000000000..62850c51c5 --- /dev/null +++ b/Nitrox.Test/Patcher/Patches/Dynamic/CreatureDeath_OnKillAsync_PatchTest.cs @@ -0,0 +1,20 @@ +using System.Collections.Generic; +using System.Linq; +using FluentAssertions; +using HarmonyLib; +using Microsoft.VisualStudio.TestTools.UnitTesting; +using NitroxTest.Patcher; + +namespace NitroxPatcher.Patches.Dynamic; + +[TestClass] +public class CreatureDeath_OnKillAsync_PatchTest +{ + [TestMethod] + public void Sanity() + { + IEnumerable originalIl = PatchTestHelper.GetInstructionsFromMethod(CreatureDeath_OnKillAsync_Patch.TARGET_METHOD); + IEnumerable transformedIl = CreatureDeath_OnKillAsync_Patch.Transpiler(originalIl); + transformedIl.Count().Should().Be(originalIl.Count() + 9); + } +} diff --git a/Nitrox.Test/Patcher/Patches/Dynamic/CreatureDeath_SpawnRespawner_PatchTest.cs b/Nitrox.Test/Patcher/Patches/Dynamic/CreatureDeath_SpawnRespawner_PatchTest.cs new file mode 100644 index 0000000000..50d716cdcc --- /dev/null +++ b/Nitrox.Test/Patcher/Patches/Dynamic/CreatureDeath_SpawnRespawner_PatchTest.cs @@ -0,0 +1,20 @@ +using System.Collections.Generic; +using System.Linq; +using FluentAssertions; +using HarmonyLib; +using Microsoft.VisualStudio.TestTools.UnitTesting; +using NitroxTest.Patcher; + +namespace NitroxPatcher.Patches.Dynamic; + +[TestClass] +public class CreatureDeath_SpawnRespawner_PatchTest +{ + [TestMethod] + public void Sanity() + { + IEnumerable originalIl = PatchTestHelper.GetInstructionsFromMethod(CreatureDeath_SpawnRespawner_Patch.TARGET_METHOD); + IEnumerable transformedIl = CreatureDeath_SpawnRespawner_Patch.Transpiler(CreatureDeath_SpawnRespawner_Patch.TARGET_METHOD, originalIl); + transformedIl.Count().Should().Be(originalIl.Count() + 2); + } +} diff --git a/Nitrox.Test/Patcher/Patches/Dynamic/Eatable_IterateDespawn_PatchTest.cs b/Nitrox.Test/Patcher/Patches/Dynamic/Eatable_IterateDespawn_PatchTest.cs new file mode 100644 index 0000000000..10336ef700 --- /dev/null +++ b/Nitrox.Test/Patcher/Patches/Dynamic/Eatable_IterateDespawn_PatchTest.cs @@ -0,0 +1,20 @@ +using System.Collections.Generic; +using System.Linq; +using FluentAssertions; +using HarmonyLib; +using Microsoft.VisualStudio.TestTools.UnitTesting; +using NitroxTest.Patcher; + +namespace NitroxPatcher.Patches.Dynamic; + +[TestClass] +public class Eatable_IterateDespawn_PatchTest +{ + [TestMethod] + public void Sanity() + { + IEnumerable originalIl = PatchTestHelper.GetInstructionsFromMethod(Eatable_IterateDespawn_Patch.TARGET_METHOD); + IEnumerable transformedIl = Eatable_IterateDespawn_Patch.Transpiler(originalIl); + transformedIl.Count().Should().Be(originalIl.Count() + 2); + } +} diff --git a/Nitrox.Test/Patcher/Patches/Dynamic/Flare_Update_PatchTest.cs b/Nitrox.Test/Patcher/Patches/Dynamic/Flare_Update_PatchTest.cs new file mode 100644 index 0000000000..dddc350efc --- /dev/null +++ b/Nitrox.Test/Patcher/Patches/Dynamic/Flare_Update_PatchTest.cs @@ -0,0 +1,20 @@ +using System.Collections.Generic; +using System.Linq; +using FluentAssertions; +using HarmonyLib; +using Microsoft.VisualStudio.TestTools.UnitTesting; +using NitroxTest.Patcher; + +namespace NitroxPatcher.Patches.Dynamic; + +[TestClass] +public class Flare_Update_PatchTest +{ + [TestMethod] + public void Sanity() + { + IEnumerable originalIl = PatchTestHelper.GetInstructionsFromMethod(Flare_Update_Patch.TARGET_METHOD); + IEnumerable transformedIl = Flare_Update_Patch.Transpiler(originalIl); + transformedIl.Count().Should().Be(originalIl.Count()); + } +} diff --git a/Nitrox.Test/Patcher/Patches/Dynamic/FootstepSounds_OnStep_PatchTest.cs b/Nitrox.Test/Patcher/Patches/Dynamic/FootstepSounds_OnStep_PatchTest.cs new file mode 100644 index 0000000000..e3c57fb34f --- /dev/null +++ b/Nitrox.Test/Patcher/Patches/Dynamic/FootstepSounds_OnStep_PatchTest.cs @@ -0,0 +1,23 @@ +//TODO: Fix with steps patch +#if SUBNAUTICA +using System.Collections.Generic; +using System.Linq; +using HarmonyLib; +using Microsoft.VisualStudio.TestTools.UnitTesting; +using NitroxTest.Patcher; + +namespace NitroxPatcher.Patches.Dynamic; + +[TestClass] +public class FootstepSounds_OnStep_PatchTest +{ + [TestMethod] + public void InjectionSanity() + { + IEnumerable beforeInstructions = PatchTestHelper.GetInstructionsFromMethod(FootstepSounds_OnStep_Patch.TARGET_METHOD); + IEnumerable result = FootstepSounds_OnStep_Patch.Transpiler(beforeInstructions); + + Assert.AreEqual(beforeInstructions.Count() + 4, result.Count()); + } +} +#endif diff --git a/Nitrox.Test/Patcher/Patches/Dynamic/IngameMenu_QuitGameAsync_PatchTest.cs b/Nitrox.Test/Patcher/Patches/Dynamic/IngameMenu_QuitGameAsync_PatchTest.cs index 3a7bf9e8c3..ebfe7d9761 100644 --- a/Nitrox.Test/Patcher/Patches/Dynamic/IngameMenu_QuitGameAsync_PatchTest.cs +++ b/Nitrox.Test/Patcher/Patches/Dynamic/IngameMenu_QuitGameAsync_PatchTest.cs @@ -24,7 +24,7 @@ public void Sanity() [TestMethod] public void InjectionSanity() { - IEnumerable beforeInstructions = PatchTestHelper.GetInstructionsFromMethod(IngameMenu_QuitGameAsync_Patch.targetMethod); + IEnumerable beforeInstructions = PatchTestHelper.GetInstructionsFromMethod(IngameMenu_QuitGameAsync_Patch.TARGET_METHOD); IEnumerable result = IngameMenu_QuitGameAsync_Patch.Transpiler(beforeInstructions); Assert.IsTrue(beforeInstructions.Count() == result.Count()); // The ifs in the target method are all false in the testing environment diff --git a/Nitrox.Test/Patcher/Patches/Dynamic/Respawn_Start_PatchTest.cs b/Nitrox.Test/Patcher/Patches/Dynamic/Respawn_Start_PatchTest.cs new file mode 100644 index 0000000000..6910ca8a4a --- /dev/null +++ b/Nitrox.Test/Patcher/Patches/Dynamic/Respawn_Start_PatchTest.cs @@ -0,0 +1,20 @@ +using System.Collections.Generic; +using System.Linq; +using FluentAssertions; +using HarmonyLib; +using Microsoft.VisualStudio.TestTools.UnitTesting; +using NitroxTest.Patcher; + +namespace NitroxPatcher.Patches.Dynamic; + +[TestClass] +public class Respawn_Start_PatchTest +{ + [TestMethod] + public void Sanity() + { + IEnumerable originalIl = PatchTestHelper.GetInstructionsFromMethod(Respawn_Start_Patch.TARGET_METHOD); + IEnumerable transformedIl = Respawn_Start_Patch.Transpiler(Respawn_Start_Patch.TARGET_METHOD, originalIl); + transformedIl.Count().Should().Be(originalIl.Count() + 3); + } +} diff --git a/Nitrox.Test/Patcher/Patches/Dynamic/SubConsoleCommand_OnConsoleCommand_sub_PatchTest.cs b/Nitrox.Test/Patcher/Patches/Dynamic/SubConsoleCommand_OnConsoleCommand_sub_PatchTest.cs new file mode 100644 index 0000000000..c2b8ddb679 --- /dev/null +++ b/Nitrox.Test/Patcher/Patches/Dynamic/SubConsoleCommand_OnConsoleCommand_sub_PatchTest.cs @@ -0,0 +1,20 @@ +using System.Collections.Generic; +using System.Linq; +using FluentAssertions; +using HarmonyLib; +using Microsoft.VisualStudio.TestTools.UnitTesting; +using NitroxTest.Patcher; + +namespace NitroxPatcher.Patches.Dynamic; + +[TestClass] +public class SubConsoleCommand_OnConsoleCommand_sub_PatchTest +{ + [TestMethod] + public void Sanity() + { + IEnumerable originalIl = PatchTestHelper.GetInstructionsFromMethod(SubConsoleCommand_OnConsoleCommand_sub_Patch.TARGET_METHOD); + IEnumerable transformedIl = SubConsoleCommand_OnConsoleCommand_sub_Patch.Transpiler(originalIl); + transformedIl.Count().Should().Be(originalIl.Count()); + } +} diff --git a/Nitrox.Test/Polyfill/PolyfillTest.cs b/Nitrox.Test/Polyfill/PolyfillTest.cs new file mode 100644 index 0000000000..7b303b0f62 --- /dev/null +++ b/Nitrox.Test/Polyfill/PolyfillTest.cs @@ -0,0 +1,69 @@ +using System.Diagnostics.CodeAnalysis; +using System.Runtime.CompilerServices; + +namespace Nitrox.Test.Polyfill; + +[TestClass] +public class PolyfillTest +{ + [TestMethod] + public void Range() + { + string value = "test"[1..]; + value.Should().Be("est"); + } + + [TestMethod] + public void Index() + { + char value = "test"[^2]; + value.Should().Be('s'); + } + + internal class TestClass + { + public required string Name { get; init; } + + public TestClass() + { + + } + + [SetsRequiredMembers] + public TestClass(string name) + { + Name = name; + } + + public string AutomaticName(int number, [CallerArgumentExpression(nameof(number))] string name = "") + { + return name; + } + + [SkipLocalsInit] + public void Stackalloc() + { + _ = stackalloc int[8]; + } + + public void Handler(string name, [InterpolatedStringHandlerArgument(nameof(name))] ref TestHandlerStruct handler) + { + } + } + + internal readonly struct UnscopedRefStruct + { + private readonly int number; + + [UnscopedRef] + public readonly ref readonly int GetRef() + { + return ref number; + } + } + [InterpolatedStringHandler] + internal struct TestHandlerStruct + { + + } +} diff --git a/Nitrox.Test/Server/Helper/XORRandomTest.cs b/Nitrox.Test/Server/Helper/XORRandomTest.cs new file mode 100644 index 0000000000..9d0ec98403 --- /dev/null +++ b/Nitrox.Test/Server/Helper/XORRandomTest.cs @@ -0,0 +1,24 @@ +using System; +using Microsoft.VisualStudio.TestTools.UnitTesting; +using NitroxServer.Helper; + +namespace Nitrox.Test.Server.Helper; + +[TestClass] +public class XORRandomTest +{ + [TestMethod] + public void TestMeanGeneration() + { + // arbitrary values under there but we can't compare the generated values with UnityEngine.Random because it's unaccessible + XORRandom.InitSeed("cheescake".GetHashCode()); + float mean = 0; + int count = 1000000; + for (int i = 0; i < count; i++) + { + mean += XORRandom.NextFloat(); + } + mean /= count; + Assert.IsTrue(Math.Abs(0.5f - mean) < 0.001f, $"Float number generation isn't uniform enough: {mean}"); + } +} diff --git a/Nitrox.Test/Server/Serialization/WorldPersistenceTest.cs b/Nitrox.Test/Server/Serialization/WorldPersistenceTest.cs index 09e2945a85..c96fa446f3 100644 --- a/Nitrox.Test/Server/Serialization/WorldPersistenceTest.cs +++ b/Nitrox.Test/Server/Serialization/WorldPersistenceTest.cs @@ -1,22 +1,16 @@ -using System; -using System.Collections.Generic; -using System.IO; -using System.Linq; -using System.Reflection; -using Microsoft.VisualStudio.TestTools.UnitTesting; using Nitrox.Test; -using Nitrox.Test.Helper; using Nitrox.Test.Helper.Faker; -using NitroxModel_Subnautica.DataStructures.GameLogic.Buildings.Rotation.Metadata; using NitroxModel.Core; +using NitroxModel.DataStructures; using NitroxModel.DataStructures.GameLogic; -using NitroxModel.DataStructures.GameLogic.Buildings.Metadata; -using NitroxServer_Subnautica; +using NitroxModel.DataStructures.GameLogic.Entities; +using NitroxModel.DataStructures.GameLogic.Entities.Bases; +using NitroxModel.DataStructures.GameLogic.Entities.Metadata; +using NitroxModel.DataStructures.GameLogic.Entities.Metadata.Bases; using NitroxServer.GameLogic; using NitroxServer.GameLogic.Unlockables; using NitroxServer.Serialization.World; -using NitroxModel.DataStructures.GameLogic.Entities; -using NitroxModel.DataStructures.GameLogic.Entities.Metadata; +using NitroxServer_Subnautica; namespace NitroxServer.Serialization; @@ -122,77 +116,10 @@ private static void StoryGoalTest(StoryGoalData storyGoal, StoryGoalData storyGo private static void StoryTimingTest(StoryTimingData storyTiming, StoryTimingData storyTimingAfter) { Assert.AreEqual(storyTiming.ElapsedSeconds, storyTimingAfter.ElapsedSeconds); +#if SUBNAUTICA Assert.AreEqual(storyTiming.AuroraCountdownTime, storyTimingAfter.AuroraCountdownTime); Assert.AreEqual(storyTiming.AuroraWarningTime, storyTimingAfter.AuroraWarningTime); - } - - [DataTestMethod, DynamicWorldDataAfter] - public void BaseDataTest(PersistedWorldData worldDataAfter, string serializerName) - { - AssertHelper.IsListEqual(worldData.BaseData.PartiallyConstructedPieces.OrderBy(x => x.Id), worldDataAfter.BaseData.PartiallyConstructedPieces.OrderBy(x => x.Id), BasePieceTest); - AssertHelper.IsListEqual(worldData.BaseData.CompletedBasePieceHistory.OrderBy(x => x.Id), worldDataAfter.BaseData.CompletedBasePieceHistory.OrderBy(x => x.Id), BasePieceTest); - } - - private static void BasePieceTest(BasePiece basePiece, BasePiece basePieceAfter) - { - Assert.AreEqual(basePiece.Id, basePieceAfter.Id); - Assert.AreEqual(basePiece.ItemPosition, basePieceAfter.ItemPosition); - Assert.AreEqual(basePiece.Rotation, basePieceAfter.Rotation); - Assert.AreEqual(basePiece.TechType, basePieceAfter.TechType); - Assert.AreEqual(basePiece.ParentId.HasValue, basePieceAfter.ParentId.HasValue); - Assert.AreEqual(basePiece.ParentId.Value, basePieceAfter.ParentId.Value); - Assert.AreEqual(basePiece.CameraPosition, basePieceAfter.CameraPosition); - Assert.AreEqual(basePiece.CameraRotation, basePieceAfter.CameraRotation); - Assert.AreEqual(basePiece.ConstructionAmount, basePieceAfter.ConstructionAmount); - Assert.AreEqual(basePiece.ConstructionCompleted, basePieceAfter.ConstructionCompleted); - Assert.AreEqual(basePiece.IsFurniture, basePieceAfter.IsFurniture); - Assert.AreEqual(basePiece.BaseId, basePieceAfter.BaseId); - Assert.AreEqual(basePiece.BuildIndex, basePieceAfter.BuildIndex); - - switch (basePiece.RotationMetadata.Value) - { - case AnchoredFaceBuilderMetadata anchoredMetadata when basePieceAfter.RotationMetadata.Value is AnchoredFaceBuilderMetadata anchoredMetadataAfter: - Assert.AreEqual(anchoredMetadata.Cell, anchoredMetadataAfter.Cell); - Assert.AreEqual(anchoredMetadata.Direction, anchoredMetadataAfter.Direction); - Assert.AreEqual(anchoredMetadata.FaceType, anchoredMetadataAfter.FaceType); - Assert.AreEqual(anchoredMetadata.Anchor, anchoredMetadataAfter.Anchor); - break; - case BaseModuleBuilderMetadata baseModuleMetadata when basePieceAfter.RotationMetadata.Value is BaseModuleBuilderMetadata baseModuleMetadataAfter: - Assert.AreEqual(baseModuleMetadata.Cell, baseModuleMetadataAfter.Cell); - Assert.AreEqual(baseModuleMetadata.Direction, baseModuleMetadataAfter.Direction); - break; - case CorridorBuilderMetadata corridorMetadata when basePieceAfter.RotationMetadata.Value is CorridorBuilderMetadata corridorMetadataAfter: - Assert.AreEqual(corridorMetadata.Rotation, corridorMetadataAfter.Rotation); - Assert.AreEqual(corridorMetadata.Position, corridorMetadataAfter.Position); - Assert.AreEqual(corridorMetadata.HasTargetBase, corridorMetadataAfter.HasTargetBase); - Assert.AreEqual(corridorMetadata.Cell, corridorMetadataAfter.Cell); - break; - case MapRoomBuilderMetadata mapRoomMetadata when basePieceAfter.RotationMetadata.Value is MapRoomBuilderMetadata mapRoomMetadataAfter: - Assert.AreEqual(mapRoomMetadata.CellType, mapRoomMetadataAfter.CellType); - Assert.AreEqual(mapRoomMetadata.Rotation, mapRoomMetadataAfter.Rotation); - break; - case null when basePieceAfter.RotationMetadata.Value is null: - break; - default: - Assert.Fail($"{nameof(BasePiece)}.{nameof(BasePiece.RotationMetadata)} is not equal"); - break; - } - - switch (basePiece.Metadata.Value) - { - case SignMetadata signMetadata when basePieceAfter.Metadata.Value is SignMetadata signMetadataAfter: - Assert.AreEqual(signMetadata.Text, signMetadataAfter.Text); - Assert.AreEqual(signMetadata.ColorIndex, signMetadataAfter.ColorIndex); - Assert.AreEqual(signMetadata.ScaleIndex, signMetadataAfter.ScaleIndex); - Assert.IsTrue(signMetadata.Elements.SequenceEqual(signMetadataAfter.Elements)); - Assert.AreEqual(signMetadata.Background, signMetadataAfter.Background); - break; - case null when basePieceAfter.Metadata.Value is null: - break; - default: - Assert.Fail($"{nameof(BasePiece)}.{nameof(BasePiece.Metadata)} is not equal"); - break; - } +#endif } [DataTestMethod, DynamicWorldDataAfter] @@ -216,7 +143,9 @@ public void PlayerDataTest(PersistedWorldData worldDataAfter, string serializerN Assert.AreEqual(playerData.CurrentStats.Health, playerDataAfter.CurrentStats.Health); Assert.AreEqual(playerData.CurrentStats.Food, playerDataAfter.CurrentStats.Food); Assert.AreEqual(playerData.CurrentStats.Water, playerDataAfter.CurrentStats.Water); +#if SUBNAUTICA Assert.AreEqual(playerData.CurrentStats.InfectionAmount, playerDataAfter.CurrentStats.InfectionAmount); +#endif Assert.AreEqual(playerData.SubRootId, playerDataAfter.SubRootId); Assert.AreEqual(playerData.Permissions, playerDataAfter.Permissions); @@ -317,6 +246,13 @@ private static void EntityTest(Entity entity, Entity entityAfter) case SeamothMetadata metadata when entityAfter.Metadata is SeamothMetadata metadataAfter: Assert.AreEqual(metadata.LightsOn, metadataAfter.LightsOn); Assert.AreEqual(metadata.Health, metadataAfter.Health); + Assert.AreEqual(metadata.Name, metadataAfter.Name); + Assert.IsTrue(metadata.Colors.SequenceEqual(metadataAfter.Colors)); + break; + case ExosuitMetadata metadata when entityAfter.Metadata is ExosuitMetadata metadataAfter: + Assert.AreEqual(metadata.Health, metadataAfter.Health); + Assert.AreEqual(metadata.Name, metadataAfter.Name); + Assert.IsTrue(metadata.Colors.SequenceEqual(metadataAfter.Colors)); break; case SubNameInputMetadata metadata when entityAfter.Metadata is SubNameInputMetadata metadataAfter: Assert.AreEqual(metadata.Name, metadataAfter.Name); @@ -345,6 +281,53 @@ private static void EntityTest(Entity entity, Entity entityAfter) Assert.AreEqual(equippedItem.TechType, equippedItemAfter.TechType); }); break; + case GhostMetadata ghostMetadata when entityAfter.Metadata is GhostMetadata ghostMetadataAfter: + Assert.AreEqual(ghostMetadata.TargetOffset, ghostMetadataAfter.TargetOffset); + + if (ghostMetadata.GetType() != ghostMetadataAfter.GetType()) + { + Assert.Fail($"Runtime type of {nameof(GhostMetadata)} in {nameof(Entity)}.{nameof(Entity.Metadata)} is not equal: {ghostMetadata.GetType().Name} - {ghostMetadataAfter.GetType().Name}"); + } + + switch (ghostMetadata) + { + case BaseAnchoredCellGhostMetadata metadata when ghostMetadataAfter is BaseAnchoredCellGhostMetadata metadataAfter: + Assert.AreEqual(metadata.AnchoredCell, metadataAfter.AnchoredCell); + break; + case BaseAnchoredFaceGhostMetadata metadata when ghostMetadataAfter is BaseAnchoredFaceGhostMetadata metadataAfter: + Assert.AreEqual(metadata.AnchoredFace, metadataAfter.AnchoredFace); + break; + case BaseDeconstructableGhostMetadata metadata when ghostMetadataAfter is BaseDeconstructableGhostMetadata metadataAfter: + Assert.AreEqual(metadata.ModuleFace, metadataAfter.ModuleFace); + Assert.AreEqual(metadata.ClassId, metadataAfter.ClassId); + break; + } + + break; + case WaterParkCreatureMetadata metadata when entityAfter.Metadata is WaterParkCreatureMetadata metadataAfter: + Assert.AreEqual(metadata.Age, metadataAfter.Age); + Assert.AreEqual(metadata.MatureTime, metadataAfter.MatureTime); + Assert.AreEqual(metadata.TimeNextBreed, metadataAfter.TimeNextBreed); + Assert.AreEqual(metadata.BornInside, metadataAfter.BornInside); + break; + case FlareMetadata metadata when entityAfter.Metadata is FlareMetadata metadataAfter: + Assert.AreEqual(metadata.EnergyLeft, metadataAfter.EnergyLeft); + Assert.AreEqual(metadata.HasBeenThrown, metadataAfter.HasBeenThrown); + Assert.AreEqual(metadata.FlareActivateTime, metadataAfter.FlareActivateTime); + break; + case BeaconMetadata metadata when entityAfter.Metadata is BeaconMetadata metadataAfter: + Assert.AreEqual(metadata.Label, metadataAfter.Label); + break; + case RadiationMetadata metadata when entityAfter.Metadata is RadiationMetadata metadataAfter: + Assert.AreEqual(metadata.Health, metadataAfter.Health); + Assert.AreEqual(metadata.FixRealTime, metadataAfter.FixRealTime); + break; + case CrashHomeMetadata metadata when entityAfter.Metadata is CrashHomeMetadata metadataAfter: + Assert.AreEqual(metadata.SpawnTime, metadataAfter.SpawnTime); + break; + case EatableMetadata metadata when entityAfter.Metadata is EatableMetadata metadataAfter: + Assert.AreEqual(metadata.TimeDecayStart, metadataAfter.TimeDecayStart); + break; default: Assert.Fail($"Runtime type of {nameof(Entity)}.{nameof(Entity.Metadata)} is not equal: {entity.Metadata?.GetType().Name} - {entityAfter.Metadata?.GetType().Name}"); break; @@ -359,8 +342,6 @@ private static void EntityTest(Entity entity, Entity entityAfter) Assert.AreEqual(worldEntity.Level, worldEntityAfter.Level); Assert.AreEqual(worldEntity.ClassId, worldEntityAfter.ClassId); Assert.AreEqual(worldEntity.SpawnedByServer, worldEntityAfter.SpawnedByServer); - Assert.AreEqual(worldEntity.WaterParkId, worldEntityAfter.WaterParkId); - Assert.AreEqual(worldEntity.ExistsInGlobalRoot, worldEntityAfter.ExistsInGlobalRoot); if (worldEntity.GetType() != worldEntityAfter.GetType()) { @@ -370,20 +351,103 @@ private static void EntityTest(Entity entity, Entity entityAfter) { switch (worldEntity) { - case PlaceholderGroupWorldEntity _ when worldEntityAfter is PlaceholderGroupWorldEntity _: + case PlaceholderGroupWorldEntity placeholderGroupWorldEntity when worldEntityAfter is PlaceholderGroupWorldEntity placeholderGroupWorldEntityAfter: + Assert.AreEqual(placeholderGroupWorldEntity.ComponentIndex, placeholderGroupWorldEntityAfter.ComponentIndex); break; - case EscapePodWorldEntity escapePodWorldEntity when worldEntityAfter is EscapePodWorldEntity escapePodWorldEntityAfter: - Assert.AreEqual(escapePodWorldEntity.Damaged, escapePodWorldEntityAfter.Damaged); - Assert.IsTrue(escapePodWorldEntity.Players.SequenceEqual(escapePodWorldEntityAfter.Players)); + case CellRootEntity _ when worldEntityAfter is CellRootEntity _: break; - case PlayerWorldEntity _ when worldEntityAfter is PlayerWorldEntity _: + case PlacedWorldEntity _ when worldEntityAfter is PlacedWorldEntity _: break; - case VehicleWorldEntity vehicleWorldEntity when worldEntityAfter is VehicleWorldEntity vehicleWorldEntityAfter: - Assert.AreEqual(vehicleWorldEntity.SpawnerId, vehicleWorldEntityAfter.SpawnerId); - Assert.AreEqual(vehicleWorldEntity.ConstructionTime, vehicleWorldEntityAfter.ConstructionTime); + case OxygenPipeEntity oxygenPipeEntity when worldEntityAfter is OxygenPipeEntity oxygenPipeEntityAfter: + Assert.AreEqual(oxygenPipeEntity.ParentPipeId, oxygenPipeEntityAfter.ParentPipeId); + Assert.AreEqual(oxygenPipeEntity.RootPipeId, oxygenPipeEntityAfter.RootPipeId); + Assert.AreEqual(oxygenPipeEntity.ParentPosition, oxygenPipeEntityAfter.ParentPosition); break; - case CellRootEntity _ when worldEntityAfter is CellRootEntity _: + case PrefabPlaceholderEntity prefabPlaceholderEntity when entityAfter is PrefabPlaceholderEntity prefabPlaceholderEntityAfter: + Assert.AreEqual(prefabPlaceholderEntity.ComponentIndex, prefabPlaceholderEntityAfter.ComponentIndex); + break; + case SerializedWorldEntity serializedWorldEntity when entityAfter is SerializedWorldEntity serializedWorldEntityAfter: + Assert.AreEqual(serializedWorldEntity.AbsoluteEntityCell, serializedWorldEntityAfter.AbsoluteEntityCell); + AssertHelper.IsListEqual(serializedWorldEntity.Components.OrderBy(c => c.GetHashCode()), serializedWorldEntityAfter.Components.OrderBy(c => c.GetHashCode()), (SerializedComponent c1, SerializedComponent c2) => c1.Equals(c2)); + Assert.AreEqual(serializedWorldEntity.Layer, serializedWorldEntityAfter.Layer); + Assert.AreEqual(serializedWorldEntity.BatchId, serializedWorldEntityAfter.BatchId); + Assert.AreEqual(serializedWorldEntity.CellId, serializedWorldEntityAfter.CellId); + break; + case GeyserWorldEntity geyserEntity when entityAfter is GeyserWorldEntity geyserEntityAfter: + Assert.AreEqual(geyserEntity.RandomIntervalVarianceMultiplier, geyserEntityAfter.RandomIntervalVarianceMultiplier); + Assert.AreEqual(geyserEntity.StartEruptTime, geyserEntityAfter.StartEruptTime); break; + case ReefbackEntity reefbackEntity when entityAfter is ReefbackEntity reefbackEntityAfter: + Assert.AreEqual(reefbackEntity.GrassIndex, reefbackEntityAfter.GrassIndex); + Assert.AreEqual(reefbackEntity.OriginalPosition, reefbackEntityAfter.OriginalPosition); + break; + case ReefbackChildEntity reefbackChildEntity when entityAfter is ReefbackChildEntity reefbackChildEntityAfter: + Assert.AreEqual(reefbackChildEntity.Type, reefbackChildEntityAfter.Type); + break; + case CreatureRespawnEntity creatureRespawnEntity when entityAfter is CreatureRespawnEntity creatureRespawnEntityAfter: + Assert.AreEqual(creatureRespawnEntity.SpawnTime, creatureRespawnEntityAfter.SpawnTime); + Assert.AreEqual(creatureRespawnEntity.RespawnTechType, creatureRespawnEntityAfter.RespawnTechType); + Assert.IsTrue(creatureRespawnEntity.AddComponents.SequenceEqual(creatureRespawnEntityAfter.AddComponents)); + break; + case GlobalRootEntity globalRootEntity when worldEntityAfter is GlobalRootEntity globalRootEntityAfter: + if (globalRootEntity.GetType() != typeof(GlobalRootEntity)) + { + switch (globalRootEntity) + { + case BuildEntity buildEntity when globalRootEntityAfter is BuildEntity buildEntityAfter: + Assert.AreEqual(buildEntity.BaseData, buildEntityAfter.BaseData); + break; +#if SUBNAUTICA + case EscapePodWorldEntity escapePodWorldEntity when globalRootEntityAfter is EscapePodWorldEntity escapePodWorldEntityAfter: + Assert.AreEqual(escapePodWorldEntity.Damaged, escapePodWorldEntityAfter.Damaged); + Assert.IsTrue(escapePodWorldEntity.Players.SequenceEqual(escapePodWorldEntityAfter.Players)); + break; +#endif + case InteriorPieceEntity interiorPieceEntity when globalRootEntityAfter is InteriorPieceEntity interiorPieceEntityAfter: + Assert.AreEqual(interiorPieceEntity.BaseFace, interiorPieceEntityAfter.BaseFace); + break; + case MapRoomEntity mapRoomEntity when globalRootEntityAfter is MapRoomEntity mapRoomEntityAfter: + Assert.AreEqual(mapRoomEntity.Cell, mapRoomEntityAfter.Cell); + break; + case ModuleEntity moduleEntity when globalRootEntityAfter is ModuleEntity moduleEntityAfter: + Assert.AreEqual(moduleEntity.ConstructedAmount, moduleEntityAfter.ConstructedAmount); + Assert.AreEqual(moduleEntity.IsInside, moduleEntityAfter.IsInside); + + if (moduleEntity.GetType() != moduleEntityAfter.GetType()) + { + Assert.Fail($"Runtime type of {nameof(ModuleEntity)} is not equal: {moduleEntity.GetType().Name} - {moduleEntityAfter.GetType().Name}"); + } + + switch (moduleEntity) + { + case GhostEntity ghostEntity when moduleEntityAfter is GhostEntity ghostEntityAfter: + Assert.AreEqual(ghostEntity.BaseFace, ghostEntityAfter.BaseFace); + Assert.AreEqual(ghostEntity.BaseData, ghostEntityAfter.BaseData); + break; + } + + break; + case MoonpoolEntity moonpoolEntity when globalRootEntityAfter is MoonpoolEntity moonpoolEntityAfter: + Assert.AreEqual(moonpoolEntity.Cell, moonpoolEntityAfter.Cell); + break; + case PlanterEntity _ when globalRootEntityAfter is PlanterEntity: + break; + case PlayerWorldEntity _ when globalRootEntityAfter is PlayerWorldEntity: + break; + case VehicleWorldEntity vehicleWorldEntity when globalRootEntityAfter is VehicleWorldEntity vehicleWorldEntityAfter: + Assert.AreEqual(vehicleWorldEntity.SpawnerId, vehicleWorldEntityAfter.SpawnerId); + Assert.AreEqual(vehicleWorldEntity.ConstructionTime, vehicleWorldEntityAfter.ConstructionTime); + break; + case RadiationLeakEntity radiationLeakEntity when globalRootEntityAfter is RadiationLeakEntity radiationLeakEntityAfter: + Assert.AreEqual(radiationLeakEntity.ObjectIndex, radiationLeakEntityAfter.ObjectIndex); + break; + default: + Assert.Fail($"Runtime type of {nameof(GlobalRootEntity)} is not equal even after the check: {worldEntity.GetType().Name} - {globalRootEntityAfter.GetType().Name}"); + break; + } + } + break; + default: Assert.Fail($"Runtime type of {nameof(WorldEntity)} is not equal even after the check: {worldEntity.GetType().Name} - {worldEntityAfter.GetType().Name}"); break; @@ -395,9 +459,6 @@ private static void EntityTest(Entity entity, Entity entityAfter) Assert.AreEqual(prefabChildEntity.ComponentIndex, prefabChildEntityAfter.ComponentIndex); Assert.AreEqual(prefabChildEntity.ClassId, prefabChildEntityAfter.ClassId); break; - case PrefabPlaceholderEntity prefabPlaceholderEntity when entityAfter is PrefabPlaceholderEntity prefabPlaceholderEntityAfter: - Assert.AreEqual(prefabPlaceholderEntity.ClassId, prefabPlaceholderEntityAfter.ClassId); - break; case InventoryEntity inventoryEntity when entityAfter is InventoryEntity inventoryEntityAfter: Assert.AreEqual(inventoryEntity.ComponentIndex, inventoryEntityAfter.ComponentIndex); break; @@ -413,6 +474,10 @@ private static void EntityTest(Entity entity, Entity entityAfter) Assert.AreEqual(installedModuleEntity.Slot, installedModuleEntityAfter.Slot); Assert.AreEqual(installedModuleEntity.ClassId, installedModuleEntityAfter.ClassId); break; + case BaseLeakEntity baseLeakEntity when entityAfter is BaseLeakEntity baseLeakEntityAfter: + Assert.AreEqual(baseLeakEntity.Health, baseLeakEntityAfter.Health); + Assert.AreEqual(baseLeakEntity.RelativeCell, baseLeakEntityAfter.RelativeCell); + break; default: Assert.Fail($"Runtime type of {nameof(Entity)} is not equal: {entity.GetType().Name} - {entityAfter.GetType().Name}"); break; diff --git a/Nitrox.Test/SetupAssemblyInitializer.cs b/Nitrox.Test/SetupAssemblyInitializer.cs index ebef90e2ad..1ffb6a075e 100644 --- a/Nitrox.Test/SetupAssemblyInitializer.cs +++ b/Nitrox.Test/SetupAssemblyInitializer.cs @@ -1,23 +1,17 @@ -using System.IO; +global using Nitrox.Test.Helper; using Microsoft.VisualStudio.TestTools.UnitTesting; using NitroxModel.Helper; using NitroxModel.Logger; -namespace Nitrox.Test +namespace Nitrox.Test; + +[TestClass] +public class SetupAssemblyInitializer { - [TestClass] - public class SetupAssemblyInitializer + [AssemblyInitialize] + public static void AssemblyInit(TestContext context) { - [AssemblyInitialize] - public static void AssemblyInit(TestContext context) - { - NitroxEnvironment.Set(NitroxEnvironment.Types.TESTING); - Log.Setup(); - - if (Directory.GetCurrentDirectory().Contains(@"D:\a\Nitrox\Nitrox")) //Check if environment is github actions - { - NitroxUser.PreferredGamePath = @"C:\PROGRA~2\Steam\steamapps\common\Subnautica"; - } - } + NitroxEnvironment.Set(NitroxEnvironment.Types.TESTING); + Log.Setup(); } } diff --git a/Nitrox.sln b/Nitrox.sln index afe01605f9..4ce6e30566 100644 --- a/Nitrox.sln +++ b/Nitrox.sln @@ -30,57 +30,86 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Nitrox.Test", "Nitrox.Test\ EndProject Project("{D954291E-2A0B-460D-934E-DC6B0785DB48}") = "Nitrox.Assets.Subnautica", "Nitrox.Assets.Subnautica\Nitrox.Assets.Subnautica.shproj", "{79E92B6D-5D25-4254-AC9F-FA9A1CD3CBC6}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Nitrox.Analyzers", "Nitrox.Analyzers\Nitrox.Analyzers.csproj", "{EB99BD64-EF43-4B06-BBFB-EB5DFA96E55D}" -EndProject Global - GlobalSection(SharedMSBuildProjectFiles) = preSolution - Nitrox.Assets.Subnautica\Nitrox.Assets.Subnautica.projitems*{79e92b6d-5d25-4254-ac9f-fa9a1cd3cbc6}*SharedItemsImports = 13 - EndGlobalSection GlobalSection(SolutionConfigurationPlatforms) = preSolution + BelowZero|Any CPU = BelowZero|Any CPU Debug|Any CPU = Debug|Any CPU Release|Any CPU = Release|Any CPU + Subnautica|Any CPU = Subnautica|Any CPU EndGlobalSection GlobalSection(ProjectConfigurationPlatforms) = postSolution + {CB7FAEFC-D9C0-40B8-A6D5-8B284683E79E}.BelowZero|Any CPU.ActiveCfg = BelowZero|Any CPU + {CB7FAEFC-D9C0-40B8-A6D5-8B284683E79E}.BelowZero|Any CPU.Build.0 = BelowZero|Any CPU {CB7FAEFC-D9C0-40B8-A6D5-8B284683E79E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {CB7FAEFC-D9C0-40B8-A6D5-8B284683E79E}.Debug|Any CPU.Build.0 = Debug|Any CPU {CB7FAEFC-D9C0-40B8-A6D5-8B284683E79E}.Release|Any CPU.ActiveCfg = Release|Any CPU {CB7FAEFC-D9C0-40B8-A6D5-8B284683E79E}.Release|Any CPU.Build.0 = Release|Any CPU + {CB7FAEFC-D9C0-40B8-A6D5-8B284683E79E}.Subnautica|Any CPU.ActiveCfg = Subnautica|Any CPU + {CB7FAEFC-D9C0-40B8-A6D5-8B284683E79E}.Subnautica|Any CPU.Build.0 = Subnautica|Any CPU + {EBEBC7DC-FAE3-4FBC-BDD3-38ED8FC072D9}.BelowZero|Any CPU.ActiveCfg = BelowZero|Any CPU + {EBEBC7DC-FAE3-4FBC-BDD3-38ED8FC072D9}.BelowZero|Any CPU.Build.0 = BelowZero|Any CPU {EBEBC7DC-FAE3-4FBC-BDD3-38ED8FC072D9}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {EBEBC7DC-FAE3-4FBC-BDD3-38ED8FC072D9}.Debug|Any CPU.Build.0 = Debug|Any CPU {EBEBC7DC-FAE3-4FBC-BDD3-38ED8FC072D9}.Release|Any CPU.ActiveCfg = Release|Any CPU {EBEBC7DC-FAE3-4FBC-BDD3-38ED8FC072D9}.Release|Any CPU.Build.0 = Release|Any CPU + {EBEBC7DC-FAE3-4FBC-BDD3-38ED8FC072D9}.Subnautica|Any CPU.ActiveCfg = Subnautica|Any CPU + {EBEBC7DC-FAE3-4FBC-BDD3-38ED8FC072D9}.Subnautica|Any CPU.Build.0 = Subnautica|Any CPU + {59EB8953-864F-4147-A210-7FC97E1A5294}.BelowZero|Any CPU.ActiveCfg = BelowZero|Any CPU + {59EB8953-864F-4147-A210-7FC97E1A5294}.BelowZero|Any CPU.Build.0 = BelowZero|Any CPU {59EB8953-864F-4147-A210-7FC97E1A5294}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {59EB8953-864F-4147-A210-7FC97E1A5294}.Debug|Any CPU.Build.0 = Debug|Any CPU {59EB8953-864F-4147-A210-7FC97E1A5294}.Release|Any CPU.ActiveCfg = Release|Any CPU {59EB8953-864F-4147-A210-7FC97E1A5294}.Release|Any CPU.Build.0 = Release|Any CPU + {59EB8953-864F-4147-A210-7FC97E1A5294}.Subnautica|Any CPU.ActiveCfg = Subnautica|Any CPU + {59EB8953-864F-4147-A210-7FC97E1A5294}.Subnautica|Any CPU.Build.0 = Subnautica|Any CPU + {39E377AD-2163-4428-952D-EBECD402C8F3}.BelowZero|Any CPU.ActiveCfg = BelowZero|Any CPU + {39E377AD-2163-4428-952D-EBECD402C8F3}.BelowZero|Any CPU.Build.0 = BelowZero|Any CPU {39E377AD-2163-4428-952D-EBECD402C8F3}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {39E377AD-2163-4428-952D-EBECD402C8F3}.Debug|Any CPU.Build.0 = Debug|Any CPU {39E377AD-2163-4428-952D-EBECD402C8F3}.Release|Any CPU.ActiveCfg = Release|Any CPU {39E377AD-2163-4428-952D-EBECD402C8F3}.Release|Any CPU.Build.0 = Release|Any CPU + {39E377AD-2163-4428-952D-EBECD402C8F3}.Subnautica|Any CPU.ActiveCfg = Subnautica|Any CPU + {39E377AD-2163-4428-952D-EBECD402C8F3}.Subnautica|Any CPU.Build.0 = Subnautica|Any CPU + {47D774E0-750C-427B-8C38-F8F985114A2E}.BelowZero|Any CPU.ActiveCfg = BelowZero|Any CPU + {47D774E0-750C-427B-8C38-F8F985114A2E}.BelowZero|Any CPU.Build.0 = BelowZero|Any CPU {47D774E0-750C-427B-8C38-F8F985114A2E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {47D774E0-750C-427B-8C38-F8F985114A2E}.Debug|Any CPU.Build.0 = Debug|Any CPU {47D774E0-750C-427B-8C38-F8F985114A2E}.Release|Any CPU.ActiveCfg = Release|Any CPU {47D774E0-750C-427B-8C38-F8F985114A2E}.Release|Any CPU.Build.0 = Release|Any CPU + {47D774E0-750C-427B-8C38-F8F985114A2E}.Subnautica|Any CPU.ActiveCfg = Subnautica|Any CPU + {47D774E0-750C-427B-8C38-F8F985114A2E}.Subnautica|Any CPU.Build.0 = Subnautica|Any CPU + {5453E724-5A8B-46A4-850B-1F17FA2E938D}.BelowZero|Any CPU.ActiveCfg = BelowZero|Any CPU + {5453E724-5A8B-46A4-850B-1F17FA2E938D}.BelowZero|Any CPU.Build.0 = BelowZero|Any CPU {5453E724-5A8B-46A4-850B-1F17FA2E938D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {5453E724-5A8B-46A4-850B-1F17FA2E938D}.Debug|Any CPU.Build.0 = Debug|Any CPU {5453E724-5A8B-46A4-850B-1F17FA2E938D}.Release|Any CPU.ActiveCfg = Release|Any CPU {5453E724-5A8B-46A4-850B-1F17FA2E938D}.Release|Any CPU.Build.0 = Release|Any CPU + {5453E724-5A8B-46A4-850B-1F17FA2E938D}.Subnautica|Any CPU.ActiveCfg = Subnautica|Any CPU + {5453E724-5A8B-46A4-850B-1F17FA2E938D}.Subnautica|Any CPU.Build.0 = Subnautica|Any CPU + {77692FDB-F713-41F1-B2AB-9019457B8909}.BelowZero|Any CPU.ActiveCfg = BelowZero|Any CPU + {77692FDB-F713-41F1-B2AB-9019457B8909}.BelowZero|Any CPU.Build.0 = BelowZero|Any CPU {77692FDB-F713-41F1-B2AB-9019457B8909}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {77692FDB-F713-41F1-B2AB-9019457B8909}.Debug|Any CPU.Build.0 = Debug|Any CPU {77692FDB-F713-41F1-B2AB-9019457B8909}.Release|Any CPU.ActiveCfg = Release|Any CPU {77692FDB-F713-41F1-B2AB-9019457B8909}.Release|Any CPU.Build.0 = Release|Any CPU + {77692FDB-F713-41F1-B2AB-9019457B8909}.Subnautica|Any CPU.ActiveCfg = Subnautica|Any CPU + {77692FDB-F713-41F1-B2AB-9019457B8909}.Subnautica|Any CPU.Build.0 = Subnautica|Any CPU + {0CD6846B-EDA6-4FFD-A540-2A46CC1074BF}.BelowZero|Any CPU.ActiveCfg = BelowZero|Any CPU + {0CD6846B-EDA6-4FFD-A540-2A46CC1074BF}.BelowZero|Any CPU.Build.0 = BelowZero|Any CPU {0CD6846B-EDA6-4FFD-A540-2A46CC1074BF}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {0CD6846B-EDA6-4FFD-A540-2A46CC1074BF}.Debug|Any CPU.Build.0 = Debug|Any CPU {0CD6846B-EDA6-4FFD-A540-2A46CC1074BF}.Release|Any CPU.ActiveCfg = Release|Any CPU {0CD6846B-EDA6-4FFD-A540-2A46CC1074BF}.Release|Any CPU.Build.0 = Release|Any CPU + {0CD6846B-EDA6-4FFD-A540-2A46CC1074BF}.Subnautica|Any CPU.ActiveCfg = Subnautica|Any CPU + {0CD6846B-EDA6-4FFD-A540-2A46CC1074BF}.Subnautica|Any CPU.Build.0 = Subnautica|Any CPU + {E4D8C360-34E4-4BE6-909F-3791DD9169B5}.BelowZero|Any CPU.ActiveCfg = BelowZero|Any CPU + {E4D8C360-34E4-4BE6-909F-3791DD9169B5}.BelowZero|Any CPU.Build.0 = BelowZero|Any CPU {E4D8C360-34E4-4BE6-909F-3791DD9169B5}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {E4D8C360-34E4-4BE6-909F-3791DD9169B5}.Debug|Any CPU.Build.0 = Debug|Any CPU {E4D8C360-34E4-4BE6-909F-3791DD9169B5}.Release|Any CPU.ActiveCfg = Release|Any CPU {E4D8C360-34E4-4BE6-909F-3791DD9169B5}.Release|Any CPU.Build.0 = Release|Any CPU - {EB99BD64-EF43-4B06-BBFB-EB5DFA96E55D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {EB99BD64-EF43-4B06-BBFB-EB5DFA96E55D}.Debug|Any CPU.Build.0 = Debug|Any CPU - {EB99BD64-EF43-4B06-BBFB-EB5DFA96E55D}.Release|Any CPU.ActiveCfg = Release|Any CPU - {EB99BD64-EF43-4B06-BBFB-EB5DFA96E55D}.Release|Any CPU.Build.0 = Release|Any CPU + {E4D8C360-34E4-4BE6-909F-3791DD9169B5}.Subnautica|Any CPU.ActiveCfg = Subnautica|Any CPU + {E4D8C360-34E4-4BE6-909F-3791DD9169B5}.Subnautica|Any CPU.Build.0 = Subnautica|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE @@ -88,4 +117,7 @@ Global GlobalSection(ExtensibilityGlobals) = postSolution SolutionGuid = {AC56EA37-FBBC-4D19-8796-29A42A2331A2} EndGlobalSection + GlobalSection(SharedMSBuildProjectFiles) = preSolution + Nitrox.Assets.Subnautica\Nitrox.Assets.Subnautica.projitems*{79e92b6d-5d25-4254-ac9f-fa9a1cd3cbc6}*SharedItemsImports = 13 + EndGlobalSection EndGlobal diff --git a/Nitrox.sln.DotSettings b/Nitrox.sln.DotSettings index 9224770077..2acdc6c8c4 100644 --- a/Nitrox.sln.DotSettings +++ b/Nitrox.sln.DotSettings @@ -110,6 +110,17 @@ <Policy Inspect="True" Prefix="" Suffix="" Style="aaBb" /> <Policy Inspect="True" Prefix="" Suffix="" Style="aaBb" /> <Policy Inspect="True" Prefix="" Suffix="" Style="AaBb" /> + <Policy Inspect="True" Prefix="" Suffix="" Style="AaBb_AaBb"><ExtraRule Prefix="" Suffix="" Style="AaBb" /></Policy> + <Policy><Descriptor Staticness="Static" AccessRightKinds="Private" Description="Static readonly fields (private)"><ElementKinds><Kind Name="READONLY_FIELD" /></ElementKinds></Descriptor><Policy Inspect="True" Prefix="" Suffix="" Style="aaBb" /></Policy> + <Policy><Descriptor Staticness="Any" AccessRightKinds="Private" Description="Constant fields (private)"><ElementKinds><Kind Name="CONSTANT_FIELD" /></ElementKinds></Descriptor><Policy Inspect="True" Prefix="" Suffix="" Style="AA_BB" /></Policy> + <Policy><Descriptor Staticness="Instance" AccessRightKinds="Private" Description="Instance fields (private)"><ElementKinds><Kind Name="FIELD" /><Kind Name="READONLY_FIELD" /></ElementKinds></Descriptor><Policy Inspect="True" Prefix="" Suffix="" Style="aaBb" /></Policy> + <Policy><Descriptor Staticness="Any" AccessRightKinds="Protected, ProtectedInternal, Internal, Public, PrivateProtected" Description="Constant fields (not private)"><ElementKinds><Kind Name="CONSTANT_FIELD" /></ElementKinds></Descriptor><Policy Inspect="True" Prefix="" Suffix="" Style="AA_BB" /></Policy> + <Policy><Descriptor Staticness="Any" AccessRightKinds="Any" Description="Parameters"><ElementKinds><Kind Name="PARAMETER" /></ElementKinds></Descriptor><Policy Inspect="True" Prefix="" Suffix="" Style="aaBb"><ExtraRule Prefix="_" Suffix="" Style="aaBb" /><ExtraRule Prefix="__" Suffix="" Style="aaBb" /><ExtraRule Prefix="___" Suffix="" Style="aaBb" /><ExtraRule Prefix="____" Suffix="" Style="aaBb" /></Policy></Policy> + <Policy><Descriptor Staticness="Any" AccessRightKinds="Any" Description="Enum members"><ElementKinds><Kind Name="ENUM_MEMBER" /></ElementKinds></Descriptor><Policy Inspect="True" Prefix="" Suffix="" Style="AA_BB" /></Policy> + <Policy><Descriptor Staticness="Any" AccessRightKinds="Any" Description="Types and namespaces"><ElementKinds><Kind Name="NAMESPACE" /><Kind Name="CLASS" /><Kind Name="STRUCT" /><Kind Name="ENUM" /><Kind Name="DELEGATE" /></ElementKinds></Descriptor><Policy Inspect="True" Prefix="" Suffix="" Style="AaBb_AaBb"><ExtraRule Prefix="" Suffix="" Style="AaBb" /></Policy></Policy> + <Policy><Descriptor Staticness="Any" AccessRightKinds="Any" Description="Local constants"><ElementKinds><Kind Name="LOCAL_CONSTANT" /></ElementKinds></Descriptor><Policy Inspect="True" Prefix="" Suffix="" Style="AA_BB" /></Policy> + <Policy><Descriptor Staticness="Any" AccessRightKinds="Any" Description="Properties"><ElementKinds><Kind Name="PROPERTY" /></ElementKinds></Descriptor><Policy Inspect="True" Prefix="" Suffix="" Style="AaBb" /></Policy> + <Policy><Descriptor Staticness="Static" AccessRightKinds="Private" Description="Static fields (private)"><ElementKinds><Kind Name="FIELD" /></ElementKinds></Descriptor><Policy Inspect="True" Prefix="" Suffix="" Style="aaBb" /></Policy> RB True True @@ -293,12 +304,14 @@ </TypePattern> </Patterns> True + True True True True True True True + True True True True @@ -307,6 +320,7 @@ True True True + True True True True @@ -316,6 +330,7 @@ True True True + True True True True diff --git a/NitroxClient/ClientAutoFacRegistrar.cs b/NitroxClient/ClientAutoFacRegistrar.cs index 2093e76a07..c22626d098 100644 --- a/NitroxClient/ClientAutoFacRegistrar.cs +++ b/NitroxClient/ClientAutoFacRegistrar.cs @@ -1,4 +1,6 @@ +global using NitroxClient.Helpers; global using NitroxModel.Logger; +global using static NitroxModel.Extensions; using System.Reflection; using Autofac; using Autofac.Core; @@ -10,25 +12,23 @@ using NitroxClient.Debuggers; using NitroxClient.Debuggers.Drawer; using NitroxClient.GameLogic; -using NitroxClient.GameLogic.Bases; -using NitroxClient.GameLogic.Bases.Spawning.BasePiece; using NitroxClient.GameLogic.ChatUI; using NitroxClient.GameLogic.FMOD; using NitroxClient.GameLogic.HUD; -using NitroxClient.GameLogic.InitialSync.Base; +using NitroxClient.GameLogic.InitialSync.Abstract; using NitroxClient.GameLogic.PlayerLogic; using NitroxClient.GameLogic.PlayerLogic.PlayerModel; using NitroxClient.GameLogic.PlayerLogic.PlayerModel.Abstract; using NitroxClient.GameLogic.PlayerLogic.PlayerPreferences; using NitroxClient.GameLogic.Settings; using NitroxClient.GameLogic.Spawning.Metadata; -using NitroxClient.GameLogic.Spawning.Metadata.Extractor; -using NitroxClient.Helpers; +using NitroxClient.GameLogic.Spawning.Metadata.Extractor.Abstract; +using NitroxClient.GameLogic.Spawning.Metadata.Processor.Abstract; using NitroxClient.Map; +using NitroxModel; using NitroxModel.Core; -using NitroxModel.DataStructures.GameLogic.Buildings.Rotation; +using NitroxModel.GameLogic.FMOD; using NitroxModel.Helper; -using NitroxModel_Subnautica.DataStructures.GameLogic.Buildings.Rotation; using NitroxModel_Subnautica.Helper; namespace NitroxClient @@ -51,12 +51,13 @@ public void RegisterDependencies(ContainerBuilder containerBuilder) } RegisterCoreDependencies(containerBuilder); + RegisterMetadataDependencies(containerBuilder); RegisterPacketProcessors(containerBuilder); RegisterColorSwapManagers(containerBuilder); RegisterInitialSyncProcessors(containerBuilder); } - private static void RegisterCoreDependencies(ContainerBuilder containerBuilder) + private void RegisterCoreDependencies(ContainerBuilder containerBuilder) { #if DEBUG containerBuilder.RegisterAssemblyTypes(currentAssembly) @@ -65,16 +66,6 @@ private static void RegisterCoreDependencies(ContainerBuilder containerBuilder) .AsImplementedInterfaces() .AsSelf() .SingleInstance(); - - containerBuilder.RegisterAssemblyTypes(currentAssembly) - .AssignableTo() - .As() - .SingleInstance(); - - containerBuilder.RegisterAssemblyTypes(currentAssembly) - .AssignableTo() - .As() - .SingleInstance(); #endif containerBuilder.Register(c => new NitroxProtobufSerializer($"{nameof(NitroxModel)}.dll")); @@ -98,26 +89,10 @@ private static void RegisterCoreDependencies(ContainerBuilder containerBuilder) .As() .InstancePerLifetimeScope(); - containerBuilder.RegisterType() - .As() - .InstancePerLifetimeScope(); - containerBuilder.RegisterType() .As() .InstancePerLifetimeScope(); - containerBuilder.RegisterAssemblyTypes(currentAssembly) - .AssignableTo() - .As() - .AsSelf() - .SingleInstance(); - - containerBuilder.RegisterAssemblyTypes(currentAssembly) - .AssignableTo() - .As() - .AsSelf() - .SingleInstance(); - containerBuilder.RegisterType().InstancePerLifetimeScope(); containerBuilder.RegisterType().InstancePerLifetimeScope(); containerBuilder.RegisterType().InstancePerLifetimeScope(); @@ -126,28 +101,27 @@ private static void RegisterCoreDependencies(ContainerBuilder containerBuilder) containerBuilder.RegisterType().InstancePerLifetimeScope(); containerBuilder.RegisterType().InstancePerLifetimeScope(); containerBuilder.RegisterType().InstancePerLifetimeScope(); - containerBuilder.RegisterType().InstancePerLifetimeScope(); containerBuilder.RegisterType().InstancePerLifetimeScope(); + containerBuilder.RegisterType().InstancePerLifetimeScope(); + containerBuilder.RegisterType().InstancePerLifetimeScope(); containerBuilder.RegisterType().InstancePerLifetimeScope(); containerBuilder.RegisterType().InstancePerLifetimeScope(); containerBuilder.RegisterType().InstancePerLifetimeScope(); containerBuilder.RegisterType().InstancePerLifetimeScope(); containerBuilder.RegisterType().InstancePerLifetimeScope(); - containerBuilder.RegisterType().InstancePerLifetimeScope(); containerBuilder.RegisterType().InstancePerLifetimeScope(); containerBuilder.RegisterType().InstancePerLifetimeScope(); containerBuilder.RegisterType().InstancePerLifetimeScope(); containerBuilder.RegisterType().InstancePerLifetimeScope(); - containerBuilder.RegisterType().InstancePerLifetimeScope(); containerBuilder.RegisterType().InstancePerLifetimeScope(); containerBuilder.RegisterType().InstancePerLifetimeScope(); - containerBuilder.RegisterType().InstancePerLifetimeScope(); - containerBuilder.RegisterType().InstancePerLifetimeScope(); containerBuilder.RegisterType().InstancePerLifetimeScope(); +#if SUBNAUTICA containerBuilder.RegisterType().InstancePerLifetimeScope(); +#endif containerBuilder.RegisterType().InstancePerLifetimeScope(); + containerBuilder.Register(_ => new FMODWhitelist(GameInfo.Subnautica)).InstancePerLifetimeScope(); containerBuilder.RegisterType().InstancePerLifetimeScope(); - containerBuilder.RegisterType().InstancePerLifetimeScope(); containerBuilder.RegisterType().InstancePerLifetimeScope(); containerBuilder.RegisterType().InstancePerLifetimeScope(); containerBuilder.RegisterType().InstancePerLifetimeScope(); @@ -155,6 +129,21 @@ private static void RegisterCoreDependencies(ContainerBuilder containerBuilder) containerBuilder.RegisterType().InstancePerLifetimeScope(); } + private void RegisterMetadataDependencies(ContainerBuilder containerBuilder) + { + containerBuilder.RegisterAssemblyTypes(currentAssembly) + .AssignableTo() + .As() + .AsSelf() + .SingleInstance(); + containerBuilder.RegisterAssemblyTypes(currentAssembly) + .AssignableTo() + .As() + .AsSelf() + .SingleInstance(); + containerBuilder.RegisterType().InstancePerLifetimeScope(); + } + private void RegisterPacketProcessors(ContainerBuilder containerBuilder) { containerBuilder @@ -176,8 +165,8 @@ private void RegisterInitialSyncProcessors(ContainerBuilder containerBuilder) { containerBuilder .RegisterAssemblyTypes(currentAssembly) - .AssignableTo() - .As() + .AssignableTo() + .As() .InstancePerLifetimeScope(); } } diff --git a/NitroxClient/Communication/MultiplayerSession/MultiplayerSessionManager.cs b/NitroxClient/Communication/MultiplayerSession/MultiplayerSessionManager.cs index 3d830faaee..5554ca0af7 100644 --- a/NitroxClient/Communication/MultiplayerSession/MultiplayerSessionManager.cs +++ b/NitroxClient/Communication/MultiplayerSession/MultiplayerSessionManager.cs @@ -1,5 +1,4 @@ using System; -using System.Collections.Generic; using System.Threading.Tasks; using NitroxClient.Communication.Abstract; using NitroxClient.Communication.MultiplayerSession.ConnectionState; @@ -63,11 +62,17 @@ public void ProcessSessionPolicy(MultiplayerSessionPolicy policy) switch (nitroxVersion.CompareTo(SessionPolicy.NitroxVersionAllowed)) { case -1: - Log.InGame($"Your Nitrox installation is out of date. Server: {SessionPolicy.NitroxVersionAllowed}, Yours: {localVersion}."); + Log.Error($"Client is out of date. Server: {SessionPolicy.NitroxVersionAllowed}, Client: {localVersion}"); + Log.InGame(Language.main.Get("Nitrox_OutOfDateClient") + .Replace("{serverVersion}", SessionPolicy.NitroxVersionAllowed.ToString()) + .Replace("{localVersion}", localVersion.ToString())); CurrentState.Disconnect(this); return; case 1: - Log.InGame($"The server runs an older version of Nitrox. Ask the server admin to upgrade or downgrade your Nitrox installation. Server: {SessionPolicy.NitroxVersionAllowed}, Yours: {localVersion}."); + Log.Error($"Server is out of date. Server: {SessionPolicy.NitroxVersionAllowed}, Client: {localVersion}"); + Log.InGame(Language.main.Get("Nitrox_OutOfDateServer") + .Replace("{serverVersion}", SessionPolicy.NitroxVersionAllowed.ToString()) + .Replace("{localVersion}", localVersion.ToString())); CurrentState.Disconnect(this); return; } @@ -80,6 +85,7 @@ public void RequestSessionReservation(PlayerSettings playerSettings, Authenticat // If a reservation has already been sent (in which case the client is enqueued in the join queue) if (CurrentState.CurrentStage == MultiplayerSessionConnectionStage.AWAITING_SESSION_RESERVATION) { + Log.Info("Waiting in join queue…"); Log.InGame(Language.main.Get("Nitrox_Waiting")); return; } @@ -93,6 +99,7 @@ public void ProcessReservationResponsePacket(MultiplayerSessionReservation reser { if (reservation.ReservationState == MultiplayerSessionReservationState.ENQUEUED_IN_JOIN_QUEUE) { + Log.Info("Waiting in join queue…"); Log.InGame(Language.main.Get("Nitrox_Waiting")); return; } diff --git a/NitroxClient/Communication/NetworkingLayer/LiteNetLib/LiteNetLibClient.cs b/NitroxClient/Communication/NetworkingLayer/LiteNetLib/LiteNetLibClient.cs index ec81024360..faaa337510 100644 --- a/NitroxClient/Communication/NetworkingLayer/LiteNetLib/LiteNetLibClient.cs +++ b/NitroxClient/Communication/NetworkingLayer/LiteNetLib/LiteNetLibClient.cs @@ -6,7 +6,7 @@ using NitroxClient.Communication.Abstract; using NitroxClient.Debuggers; using NitroxClient.MonoBehaviours; -using NitroxClient.MonoBehaviours.Gui.InGame; +using NitroxClient.MonoBehaviours.Gui.Modals; using NitroxModel.Networking; using NitroxModel.Packets; @@ -14,28 +14,19 @@ namespace NitroxClient.Communication.NetworkingLayer.LiteNetLib; public class LiteNetLibClient : IClient { - public bool IsConnected { get; private set; } + private readonly NetManager client; private readonly AutoResetEvent connectedEvent = new(false); private readonly NetDataWriter dataWriter = new(); - private readonly PacketReceiver packetReceiver; private readonly INetworkDebugger networkDebugger; - - private NetManager client; + private readonly PacketReceiver packetReceiver; + public bool IsConnected { get; private set; } public LiteNetLibClient(PacketReceiver packetReceiver, INetworkDebugger networkDebugger = null) { this.packetReceiver = packetReceiver; this.networkDebugger = networkDebugger; - } - - public async Task StartAsync(string ipAddress, int serverPort) - { - Log.Info("Initializing LiteNetLibClient..."); - - SynchronizationContext.SetSynchronizationContext(new SynchronizationContext()); - - EventBasedNetListener listener = new EventBasedNetListener(); + EventBasedNetListener listener = new(); listener.PeerConnectedEvent += Connected; listener.PeerDisconnectedEvent += Disconnected; listener.NetworkReceiveEvent += ReceivedNetworkData; @@ -47,12 +38,19 @@ public async Task StartAsync(string ipAddress, int serverPort) DisconnectTimeout = 300000 //Disables Timeout (for 5 min) for debug purpose (like if you jump though the server code) #endif }; + } + + public async Task StartAsync(string ipAddress, int serverPort) + { + Log.Info("Initializing LiteNetLibClient..."); + // ConfigureAwait(false) is needed because Unity uses a custom "UnitySynchronizationContext". Which makes async/await work like Unity coroutines. + // Because this Task.Run is async-over-sync this would otherwise blocks the main thread as it wants to, without ConfigureAwait(false), continue on the same thread (i.e. main thread). await Task.Run(() => { client.Start(); client.Connect(ipAddress, serverPort, "nitrox"); - }); + }).ConfigureAwait(false); connectedEvent.WaitOne(2000); connectedEvent.Reset(); @@ -76,7 +74,7 @@ public void Stop() } /// - /// This should be called once each game tick + /// This should be called once each game tick /// public void PollEvents() => client.PollEvents(); @@ -88,7 +86,7 @@ private void ReceivedNetworkData(NetPeer peer, NetDataReader reader, byte channe { reader.GetBytes(packetData, packetDataLength); Packet packet = Packet.Deserialize(packetData); - packetReceiver.PacketReceived(packet); + packetReceiver.Add(packet); networkDebugger?.PacketReceived(packet, packetDataLength); } finally diff --git a/NitroxClient/Communication/PacketReceiver.cs b/NitroxClient/Communication/PacketReceiver.cs index 545ea13a8f..dfe1959221 100644 --- a/NitroxClient/Communication/PacketReceiver.cs +++ b/NitroxClient/Communication/PacketReceiver.cs @@ -1,15 +1,15 @@ -using System.Collections.Generic; +using System; +using System.Collections.Generic; using NitroxModel.Packets; namespace NitroxClient.Communication; -// TODO: Spinlocks don't seem to be necessary here, but I don't know for certain. public class PacketReceiver { + private readonly Queue receivedPackets = new(16); private readonly object receivedPacketsLock = new(); - private readonly Queue receivedPackets = new(); - public void PacketReceived(Packet packet) + public void Add(Packet packet) { lock (receivedPacketsLock) { @@ -17,18 +17,24 @@ public void PacketReceived(Packet packet) } } - public Queue GetReceivedPackets() + public Packet GetNextPacket() { - Queue packets = new(); - lock (receivedPacketsLock) { - while (receivedPackets.Count > 0) - { - packets.Enqueue(receivedPackets.Dequeue()); - } + return receivedPackets.Count == 0 ? null : receivedPackets.Dequeue(); } + } - return packets; + /// + /// Applies an operation on each packet waiting to be processed and removes it from the queue. + /// + public void ConsumePackets(Action consumer, TExtra extraParameter) + { + Packet packet = GetNextPacket(); + while (packet != null) + { + consumer(packet, extraParameter); + packet = GetNextPacket(); + } } } diff --git a/NitroxClient/Communication/PacketSuppression.cs b/NitroxClient/Communication/PacketSuppression.cs deleted file mode 100644 index b006a0f265..0000000000 --- a/NitroxClient/Communication/PacketSuppression.cs +++ /dev/null @@ -1,28 +0,0 @@ -using System; -using NitroxModel.Packets; - -namespace NitroxClient.Communication; - -/// -/// Suppresses the given packet type from being sent. Disables the suppression when disposed. -/// -/// The packet type to suppress. -public readonly struct PacketSuppressor : IDisposable - where T : Packet -{ - private static bool isSuppressed; - public static bool IsSuppressed => isSuppressed; - - public static readonly PacketSuppressor Instance = new(); - - public static PacketSuppressor Suppress() - { - isSuppressed = true; - return Instance; - } - - public void Dispose() - { - isSuppressed = false; - } -} diff --git a/NitroxClient/Communication/PacketSuppressor.cs b/NitroxClient/Communication/PacketSuppressor.cs new file mode 100644 index 0000000000..99acde7758 --- /dev/null +++ b/NitroxClient/Communication/PacketSuppressor.cs @@ -0,0 +1,66 @@ +using System; +using NitroxModel.Packets; + +namespace NitroxClient.Communication; + +/// +/// Suppresses the given packet type from being sent. Disables the suppression when disposed. +/// +/// The packet type to suppress. +public readonly struct PacketSuppressor : IDisposable where T : Packet +{ + private static bool isSuppressed; + public static bool IsSuppressed => isSuppressed; + + private static readonly PacketSuppressor instance = new(); + + public static PacketSuppressor Suppress() + { + isSuppressed = true; + return instance; + } + + public void Dispose() + { + isSuppressed = false; + } +} + +/// +/// First packet type to suppress. +/// Second packet type to suppress. +/// Third packet type to suppress. +/// Fourth packet type to suppress. +/// Fifth packet type to suppress. +public readonly struct PacketSuppressor : IDisposable + where T1 : Packet + where T2 : Packet + where T3 : Packet + where T4 : Packet + where T5 : Packet +{ + private static readonly PacketSuppressor instance1 = new(); + private static readonly PacketSuppressor instance2 = new(); + private static readonly PacketSuppressor instance3 = new(); + private static readonly PacketSuppressor instance4 = new(); + private static readonly PacketSuppressor instance5 = new(); + + public static PacketSuppressor Suppress() + { + PacketSuppressor.Suppress(); + PacketSuppressor.Suppress(); + PacketSuppressor.Suppress(); + PacketSuppressor.Suppress(); + PacketSuppressor.Suppress(); + return new PacketSuppressor(); + } + + public void Dispose() + { + instance1.Dispose(); + instance2.Dispose(); + instance3.Dispose(); + instance4.Dispose(); + instance5.Dispose(); + } +} diff --git a/NitroxClient/Communication/Packets/Processors/AuroraAndTimeUpdateProcessor.cs b/NitroxClient/Communication/Packets/Processors/AuroraAndTimeUpdateProcessor.cs index 5d3b63b6d7..2923da2595 100644 --- a/NitroxClient/Communication/Packets/Processors/AuroraAndTimeUpdateProcessor.cs +++ b/NitroxClient/Communication/Packets/Processors/AuroraAndTimeUpdateProcessor.cs @@ -16,10 +16,13 @@ public AuroraAndTimeUpdateProcessor(TimeManager timeManager) public override void Process(AuroraAndTimeUpdate packet) { timeManager.ProcessUpdate(packet.TimeData.TimePacket); +#if SUBNAUTICA StoryManager.UpdateAuroraData(packet.TimeData.AuroraEventData); + timeManager.AuroraRealExplosionTime = packet.TimeData.AuroraEventData.AuroraRealExplosionTime; if (packet.Restore) { StoryManager.RestoreAurora(); } +#endif } } diff --git a/NitroxClient/Communication/Packets/Processors/BasePieceMetadataChangedProcessor.cs b/NitroxClient/Communication/Packets/Processors/BasePieceMetadataChangedProcessor.cs deleted file mode 100644 index 9623f8db9c..0000000000 --- a/NitroxClient/Communication/Packets/Processors/BasePieceMetadataChangedProcessor.cs +++ /dev/null @@ -1,15 +0,0 @@ -using NitroxClient.Communication.Packets.Processors.Abstract; -using NitroxClient.GameLogic.Bases.Metadata; -using NitroxModel.Packets; - -namespace NitroxClient.Communication.Packets.Processors -{ - public class BasePieceMetadataChangedProcessor : ClientPacketProcessor - { - public override void Process(BasePieceMetadataChanged packet) - { - BasePieceMetadataProcessor metadataProcessor = BasePieceMetadataProcessor.FromMetaData(packet.Metadata); - metadataProcessor.UpdateMetadata(packet.PieceId, packet.Metadata); - } - } -} diff --git a/NitroxClient/Communication/Packets/Processors/BuildProcessor.cs b/NitroxClient/Communication/Packets/Processors/BuildProcessor.cs new file mode 100644 index 0000000000..e749c99e24 --- /dev/null +++ b/NitroxClient/Communication/Packets/Processors/BuildProcessor.cs @@ -0,0 +1,29 @@ +using NitroxClient.Communication.Packets.Processors.Abstract; +using NitroxClient.GameLogic.Bases; +using NitroxModel.Packets; + +namespace NitroxClient.Communication.Packets.Processors; + +public abstract class BuildProcessor : ClientPacketProcessor where T : Packet +{ + public override void Process(T packet) + { + BuildingHandler.Main.BuildQueue.Enqueue(packet); + } +} + +public class PlaceGhostProcessor : BuildProcessor { } + +public class PlaceModuleProcessor : BuildProcessor { } + +public class ModifyConstructedAmountProcessor : BuildProcessor { } + +public class PlaceBaseProcessor : BuildProcessor { } + +public class UpdateBaseProcessor : BuildProcessor { } + +public class BaseDeconstructedProcessor : BuildProcessor { } + +public class PieceDeconstructedProcessor : BuildProcessor { } + +public class WaterParkDeconstructedProcessor : BuildProcessor { } diff --git a/NitroxClient/Communication/Packets/Processors/BuildingDesyncWarningProcessor.cs b/NitroxClient/Communication/Packets/Processors/BuildingDesyncWarningProcessor.cs new file mode 100644 index 0000000000..19f527313d --- /dev/null +++ b/NitroxClient/Communication/Packets/Processors/BuildingDesyncWarningProcessor.cs @@ -0,0 +1,31 @@ +using System.Collections.Generic; +using NitroxClient.Communication.Packets.Processors.Abstract; +using NitroxClient.GameLogic.Bases; +using NitroxClient.GameLogic.Settings; +using NitroxModel.DataStructures; +using NitroxModel.Packets; + +namespace NitroxClient.Communication.Packets.Processors; + +public class BuildingDesyncWarningProcessor : ClientPacketProcessor +{ + public override void Process(BuildingDesyncWarning packet) + { + if (!BuildingHandler.Main) + { + return; + } + + foreach (KeyValuePair operation in packet.Operations) + { + OperationTracker tracker = BuildingHandler.Main.EnsureTracker(operation.Key); + tracker.LastOperationId = operation.Value; + tracker.FailedOperations++; + } + + if (NitroxPrefs.SafeBuildingLog.Value) + { + Log.InGame(Language.main.Get("Nitrox_BuildingDesyncDetected")); + } + } +} diff --git a/NitroxClient/Communication/Packets/Processors/BuildingResyncProcessor.cs b/NitroxClient/Communication/Packets/Processors/BuildingResyncProcessor.cs new file mode 100644 index 0000000000..0d18613e27 --- /dev/null +++ b/NitroxClient/Communication/Packets/Processors/BuildingResyncProcessor.cs @@ -0,0 +1,184 @@ +using System; +using System.Collections; +using System.Collections.Generic; +using System.Diagnostics; +using System.Linq; +using NitroxClient.Communication.Packets.Processors.Abstract; +using NitroxClient.GameLogic; +using NitroxClient.GameLogic.Bases; +using NitroxClient.GameLogic.Spawning.Bases; +using NitroxClient.GameLogic.Spawning.Metadata; +using NitroxClient.MonoBehaviours; +using NitroxClient.Unity.Helper; +using NitroxModel.DataStructures; +using NitroxModel.DataStructures.GameLogic; +using NitroxModel.DataStructures.GameLogic.Entities; +using NitroxModel.DataStructures.GameLogic.Entities.Bases; +using NitroxModel.Packets; +using NitroxModel_Subnautica.DataStructures; +using UnityEngine; + +namespace NitroxClient.Communication.Packets.Processors; + +public class BuildingResyncProcessor : ClientPacketProcessor +{ + private readonly Entities entities; + private readonly EntityMetadataManager entityMetadataManager; + + public BuildingResyncProcessor(Entities entities, EntityMetadataManager entityMetadataManager) + { + this.entities = entities; + this.entityMetadataManager = entityMetadataManager; + } + + public override void Process(BuildingResync packet) + { + if (!BuildingHandler.Main) + { + return; + } + + BuildingHandler.Main.StartCoroutine(ResyncBuildingEntities(packet.BuildEntities, packet.ModuleEntities)); + } + + public IEnumerator ResyncBuildingEntities(Dictionary buildEntities, Dictionary moduleEntities) + { + Stopwatch stopwatch = Stopwatch.StartNew(); + BuildingHandler.Main.StartResync(buildEntities); + yield return UpdateEntities(buildEntities.Keys.ToList(), OverwriteBase, IsInCloseProximity).OnYieldError(exception => Log.Error(exception, $"Encountered an exception while resyncing BuildEntities")); + + BuildingHandler.Main.StartResync(moduleEntities); + yield return UpdateEntities(moduleEntities.Keys.ToList(), OverwriteModule, IsInCloseProximity).OnYieldError(exception => Log.Error(exception, $"Encountered an exception while resyncing ModuleEntities")); + BuildingHandler.Main.StopResync(); + + stopwatch.Stop(); + + int totalEntities = buildEntities.Count + moduleEntities.Count; + Log.InGame(Language.main.Get("Nitrox_FinishedResyncRequest").Replace("{TIME}", stopwatch.ElapsedMilliseconds.ToString()).Replace("{COUNT}", totalEntities.ToString())); + } + + private bool IsInCloseProximity(WorldEntity entity, C componentInWorld) where C : Component + { + return Vector3.Distance(entity.Transform.Position.ToUnity(), componentInWorld.transform.position) < 0.001f; + } + + /// + /// Tries to overwrite components of the provided type found in GlobalRoot's hierarchy by the provided list of entities to update. + /// If no component is found to be corresponding to a provided entity, the entity will be spawned independently. + /// Other components of the provided type which weren't updated shall be destroyed. + /// + /// + /// The provided list is modified by the function. Make sure it's not used somewhere else. + /// + /// The Unity component to be looked for + /// The GlobalRootEntity type which will be updated + /// A function to overwrite a given component by a given entity + /// + /// Predicate to determine if an entity can overwrite the GameObject of the provided component. + /// + public IEnumerator UpdateEntities(List entitiesToUpdate, Func overwrite, Func correspondingPredicate) where C : Component where E : GlobalRootEntity + { + List unmarkedComponents = new(); + Dictionary entitiesToUpdateById = entitiesToUpdate.ToDictionary(e => e.Id); + + foreach (Transform childTransform in LargeWorldStreamer.main.globalRoot.transform) + { + if (childTransform.TryGetComponent(out C component)) + { + if (component.TryGetNitroxId(out NitroxId id) && entitiesToUpdateById.TryGetValue(id, out E correspondingEntity)) + { + yield return overwrite(component, correspondingEntity).OnYieldError(Log.Error); + entitiesToUpdate.Remove(correspondingEntity); + continue; + } + unmarkedComponents.Add(component); + } + } + + for (int i = entitiesToUpdate.Count - 1; i >= 0; i--) + { + E entity = entitiesToUpdate[i]; + C associatedComponent = unmarkedComponents.Find(c => + correspondingPredicate(entity, c)); + yield return overwrite(associatedComponent, entity).OnYieldError(Log.Error); + + unmarkedComponents.Remove(associatedComponent); + entitiesToUpdate.RemoveAt(i); + } + + for (int i = unmarkedComponents.Count - 1; i >= 0; i--) + { + Log.Info($"[{typeof(E)} RESYNC] Destroyed GameObject {unmarkedComponents[i].gameObject}"); + GameObject.Destroy(unmarkedComponents[i].gameObject); + } + foreach (E entity in entitiesToUpdate) + { + Log.Info($"[{typeof(E)} RESYNC] spawning entity {entity.Id}"); + yield return entities.SpawnEntityAsync(entity).OnYieldError(Log.Error); + } + } + + public IEnumerator OverwriteBase(Base @base, BuildEntity buildEntity) + { + Log.Info($"[Base RESYNC] Overwriting base with id {buildEntity.Id}"); + ClearBaseChildren(@base); + yield return BuildEntitySpawner.SetupBase(buildEntity, @base, entities); + yield return MoonpoolManager.RestoreMoonpools(buildEntity.ChildEntities.OfType(), @base); + yield return entities.SpawnBatchAsync(buildEntity.ChildEntities.OfType().ToList(), false, false); + + foreach (Entity childEntity in buildEntity.ChildEntities) + { + switch (childEntity) + { + case MapRoomEntity mapRoomEntity: + yield return InteriorPieceEntitySpawner.RestoreMapRoom(@base, mapRoomEntity); + break; + case BaseLeakEntity baseLeakEntity: + yield return entities.SpawnEntityAsync(baseLeakEntity, true); + break; + } + } + } + + public IEnumerator OverwriteModule(Constructable constructable, ModuleEntity moduleEntity) + { + Log.Info($"[Module RESYNC] Overwriting module with id {moduleEntity.Id}"); + ModuleEntitySpawner.ApplyModuleData(moduleEntity, constructable.gameObject); + entityMetadataManager.ApplyMetadata(constructable.gameObject, moduleEntity.Metadata); + yield break; + } + + /// + /// Destroys manually ghosts, modules, interior pieces and vehicles of a base + /// + /// + /// This is the destructive way of clearing the base, if the base isn't modified consequently, IBaseModuleGeometry under the base cells may start spamming errors. + /// + public static void ClearBaseChildren(Base @base) + { + for (int i = @base.transform.childCount - 1; i >= 0; i--) + { + Transform child = @base.transform.GetChild(i); + if (child.GetComponent().AliveOrNull() || child.GetComponent()) + { + UnityEngine.Object.Destroy(child.gameObject); + } + } + foreach (VehicleDockingBay vehicleDockingBay in @base.GetComponentsInChildren(true)) + { +#if SUBNAUTICA + if (vehicleDockingBay.dockedVehicle) + { + UnityEngine.Object.Destroy(vehicleDockingBay.dockedVehicle.gameObject); + vehicleDockingBay.SetVehicleUndocked(); + } +#elif BELOWZERO + if (vehicleDockingBay.dockedObject) + { + UnityEngine.Object.Destroy(vehicleDockingBay.dockedObject.gameObject); + vehicleDockingBay.SetVehicleUndocked(); + } +#endif + } + } +} diff --git a/NitroxClient/Communication/Packets/Processors/ConstructionAmountChangedProcessor.cs b/NitroxClient/Communication/Packets/Processors/ConstructionAmountChangedProcessor.cs deleted file mode 100644 index 2f2fa2afaa..0000000000 --- a/NitroxClient/Communication/Packets/Processors/ConstructionAmountChangedProcessor.cs +++ /dev/null @@ -1,21 +0,0 @@ -using NitroxClient.Communication.Packets.Processors.Abstract; -using NitroxClient.GameLogic.Bases; -using NitroxModel.Packets; - -namespace NitroxClient.Communication.Packets.Processors -{ - public class ConstructionAmountChangedProcessor : ClientPacketProcessor - { - private BuildThrottlingQueue buildEventQueue; - - public ConstructionAmountChangedProcessor(BuildThrottlingQueue buildEventQueue) - { - this.buildEventQueue = buildEventQueue; - } - - public override void Process(ConstructionAmountChanged amountChanged) - { - buildEventQueue.EnqueueAmountChanged(amountChanged.Id, amountChanged.ConstructionAmount); - } - } -} diff --git a/NitroxClient/Communication/Packets/Processors/ConstructionCompletedProcessor.cs b/NitroxClient/Communication/Packets/Processors/ConstructionCompletedProcessor.cs deleted file mode 100644 index 1a30e3fdc9..0000000000 --- a/NitroxClient/Communication/Packets/Processors/ConstructionCompletedProcessor.cs +++ /dev/null @@ -1,21 +0,0 @@ -using NitroxClient.Communication.Packets.Processors.Abstract; -using NitroxClient.GameLogic.Bases; -using NitroxModel.Packets; - -namespace NitroxClient.Communication.Packets.Processors -{ - public class ConstructionCompletedProcessor : ClientPacketProcessor - { - private BuildThrottlingQueue buildEventQueue; - - public ConstructionCompletedProcessor(BuildThrottlingQueue buildEventQueue) - { - this.buildEventQueue = buildEventQueue; - } - - public override void Process(ConstructionCompleted completedPacket) - { - buildEventQueue.EnqueueConstructionCompleted(completedPacket.PieceId, completedPacket.BaseId); - } - } -} diff --git a/NitroxClient/Communication/Packets/Processors/CyclopsDamageProcessor.cs b/NitroxClient/Communication/Packets/Processors/CyclopsDamageProcessor.cs index 3da5fc5c7b..59c452ec6a 100644 --- a/NitroxClient/Communication/Packets/Processors/CyclopsDamageProcessor.cs +++ b/NitroxClient/Communication/Packets/Processors/CyclopsDamageProcessor.cs @@ -141,8 +141,11 @@ private void SetActiveRoomFires(SubRoot subRoot, CyclopsFireData[] roomFires) { SubFire subFire = subRoot.gameObject.RequireComponent(); Dictionary roomFiresDict = subFire.roomFires; - NitroxId subRootId = NitroxEntity.GetId(subRoot.gameObject); - CyclopsFireData fireNode = null; + + if (!subRoot.TryGetIdOrWarn(out NitroxId subRootId)) + { + return; + } if (roomFires != null && roomFires.Length > 0) { @@ -151,7 +154,7 @@ private void SetActiveRoomFires(SubRoot subRoot, CyclopsFireData[] roomFires) { for (int nodeIndex = 0; nodeIndex < keyValuePair.Value.spawnNodes.Length; nodeIndex++) { - fireNode = roomFires.SingleOrDefault(x => x.Room == keyValuePair.Key && x.NodeIndex == nodeIndex); + CyclopsFireData fireNode = roomFires.SingleOrDefault(x => x.Room == keyValuePair.Key && x.NodeIndex == nodeIndex); // If there's a matching node index, add a fire if there isn't one already. Otherwise remove a fire if there is one if (fireNode == null) @@ -176,11 +179,11 @@ private void SetActiveRoomFires(SubRoot subRoot, CyclopsFireData[] roomFires) { foreach (KeyValuePair keyValuePair in roomFiresDict) { - for (int nodeIndex = 0; nodeIndex < keyValuePair.Value.spawnNodes.Length; nodeIndex++) + foreach (Transform spawnNode in keyValuePair.Value.spawnNodes) { - if (keyValuePair.Value.spawnNodes[nodeIndex].childCount > 0) + if (spawnNode.childCount > 0) { - keyValuePair.Value.spawnNodes[nodeIndex].GetComponentInChildren().Douse(10000); + spawnNode.GetComponentInChildren().Douse(10000); } } } diff --git a/NitroxClient/Communication/Packets/Processors/DeconstructionCompletedProcessor.cs b/NitroxClient/Communication/Packets/Processors/DeconstructionCompletedProcessor.cs deleted file mode 100644 index bc877cb604..0000000000 --- a/NitroxClient/Communication/Packets/Processors/DeconstructionCompletedProcessor.cs +++ /dev/null @@ -1,40 +0,0 @@ -using NitroxClient.Communication.Abstract; -using NitroxClient.Communication.Packets.Processors.Abstract; -using NitroxClient.GameLogic.Bases; -using NitroxClient.MonoBehaviours; -using NitroxModel.Packets; -using UnityEngine; - -namespace NitroxClient.Communication.Packets.Processors; - -public class DeconstructionCompletedProcessor : ClientPacketProcessor -{ - private readonly GeometryRespawnManager geometryRespawnManager; - private readonly IPacketSender packetSender; - - public DeconstructionCompletedProcessor(GeometryRespawnManager geometryRespawnManager, IPacketSender packetSender) - { - this.geometryRespawnManager = geometryRespawnManager; - this.packetSender = packetSender; - } - public override void Process(DeconstructionCompleted packet) - { - GameObject deconstructing = NitroxEntity.RequireObjectFrom(packet.Id); - if (deconstructing.TryGetComponent(out Constructable constructable)) - { - constructable.constructedAmount = 0; - using (PacketSuppressor.Suppress()) - { - TaskResult result = new (); - TaskResult reason = new (); - constructable.DeconstructAsync(result, reason); - } - } - else - { - UnityEngine.Object.Destroy(deconstructing); - } - geometryRespawnManager.NitroxIdsToIgnore.Add(packet.Id); - Log.Debug($"[DeconstructionCompletedProcessor] added NitroxId to ignore list {packet.Id}"); - } -} diff --git a/NitroxClient/Communication/Packets/Processors/DisconnectProcessor.cs b/NitroxClient/Communication/Packets/Processors/DisconnectProcessor.cs index 49688a1be5..a7f9001874 100644 --- a/NitroxClient/Communication/Packets/Processors/DisconnectProcessor.cs +++ b/NitroxClient/Communication/Packets/Processors/DisconnectProcessor.cs @@ -27,7 +27,8 @@ public override void Process(Disconnect disconnect) if (remotePlayer.HasValue) { remotePlayerManager.RemovePlayer(disconnect.PlayerId); - Log.InGame($"{remotePlayer.Value.PlayerName} disconnected"); + Log.Info($"{remotePlayer.Value.PlayerName} disconnected"); + Log.InGame(Language.main.Get("Nitrox_PlayerDisconnected").Replace("{PLAYER}", remotePlayer.Value.PlayerName)); } } } diff --git a/NitroxClient/Communication/Packets/Processors/EntityDestroyedProcessor.cs b/NitroxClient/Communication/Packets/Processors/EntityDestroyedProcessor.cs index a31bbbe932..c2850b976e 100644 --- a/NitroxClient/Communication/Packets/Processors/EntityDestroyedProcessor.cs +++ b/NitroxClient/Communication/Packets/Processors/EntityDestroyedProcessor.cs @@ -23,6 +23,7 @@ public override void Process(EntityDestroyed packet) entities.RemoveEntity(packet.Id); if (!NitroxEntity.TryGetObjectFrom(packet.Id, out GameObject gameObject)) { + entities.MarkForDeletion(packet.Id); Log.Warn($"[{nameof(EntityDestroyedProcessor)}] Could not find entity with id: {packet.Id} to destroy."); return; } diff --git a/NitroxClient/Communication/Packets/Processors/EntityMetadataUpdateProcessor.cs b/NitroxClient/Communication/Packets/Processors/EntityMetadataUpdateProcessor.cs index 624c59826e..b14e30c2a4 100644 --- a/NitroxClient/Communication/Packets/Processors/EntityMetadataUpdateProcessor.cs +++ b/NitroxClient/Communication/Packets/Processors/EntityMetadataUpdateProcessor.cs @@ -1,23 +1,34 @@ -using NitroxClient.Communication.Packets.Processors.Abstract; +using NitroxClient.Communication.Packets.Processors.Abstract; using NitroxClient.GameLogic.Spawning.Metadata; +using NitroxClient.GameLogic.Spawning.Metadata.Processor.Abstract; using NitroxClient.MonoBehaviours; using NitroxModel.DataStructures.Util; using NitroxModel.Helper; using NitroxModel.Packets; using UnityEngine; -namespace NitroxClient.Communication.Packets.Processors +namespace NitroxClient.Communication.Packets.Processors; + +public class EntityMetadataUpdateProcessor : ClientPacketProcessor { - public class EntityMetadataUpdateProcessor : ClientPacketProcessor + private readonly EntityMetadataManager entityMetadataManager; + + public EntityMetadataUpdateProcessor(EntityMetadataManager entityMetadataManager) { - public override void Process(EntityMetadataUpdate update) + this.entityMetadataManager = entityMetadataManager; + } + + public override void Process(EntityMetadataUpdate update) + { + if (!NitroxEntity.TryGetObjectFrom(update.Id, out GameObject gameObject)) { - GameObject gameObject = NitroxEntity.RequireObjectFrom(update.Id); + entityMetadataManager.RegisterNewerMetadata(update.Id, update.NewValue); + return; + } - Optional metadataProcessor = EntityMetadataProcessor.FromMetaData(update.NewValue); - Validate.IsTrue(metadataProcessor.HasValue, $"No processor found for EntityMetadata of type {update.NewValue.GetType()}"); + Optional metadataProcessor = entityMetadataManager.FromMetaData(update.NewValue); + Validate.IsTrue(metadataProcessor.HasValue, $"No processor found for EntityMetadata of type {update.NewValue.GetType()}"); - metadataProcessor.Value.ProcessMetadata(gameObject, update.NewValue); - } + metadataProcessor.Value.ProcessMetadata(gameObject, update.NewValue); } } diff --git a/NitroxClient/Communication/Packets/Processors/EntityReparentedProcessor.cs b/NitroxClient/Communication/Packets/Processors/EntityReparentedProcessor.cs index 2ac56671af..1caa37195c 100644 --- a/NitroxClient/Communication/Packets/Processors/EntityReparentedProcessor.cs +++ b/NitroxClient/Communication/Packets/Processors/EntityReparentedProcessor.cs @@ -34,6 +34,25 @@ public override void Process(EntityReparented packet) GameObject newParent = NitroxEntity.RequireObjectFrom(packet.NewParentId); + if (entity.Value.TryGetComponent(out Pickupable pickupable)) + { + // If the entity is being parented to a WaterPark + if (newParent.TryGetComponent(out WaterPark waterPark)) + { + pickupable.SetVisible(false); + pickupable.Activate(false); + waterPark.AddItem(pickupable); + // The reparenting is automatic here so we don't need to continue + return; + } + // If the entity was parented to a WaterPark but is picked up by someone + else if (pickupable.TryGetComponent(out WaterParkItem waterParkItem)) + { + pickupable.Deactivate(); + waterParkItem.SetWaterPark(null); + } + } + using (PacketSuppressor.Suppress()) { Type entityType = entities.RequireEntityType(packet.Id); diff --git a/NitroxClient/Communication/Packets/Processors/EscapePodChangedProcessor.cs b/NitroxClient/Communication/Packets/Processors/EscapePodChangedProcessor.cs index 758d926d8a..d464a7ea42 100644 --- a/NitroxClient/Communication/Packets/Processors/EscapePodChangedProcessor.cs +++ b/NitroxClient/Communication/Packets/Processors/EscapePodChangedProcessor.cs @@ -1,4 +1,5 @@ -using NitroxClient.Communication.Packets.Processors.Abstract; +#if SUBNAUTICA +using NitroxClient.Communication.Packets.Processors.Abstract; using NitroxClient.GameLogic; using NitroxClient.MonoBehaviours; using NitroxModel.DataStructures.Util; @@ -35,5 +36,4 @@ public override void Process(EscapePodChanged packet) } } } - - +#endif diff --git a/NitroxClient/Communication/Packets/Processors/ExosuitArmActionProcessor.cs b/NitroxClient/Communication/Packets/Processors/ExosuitArmActionProcessor.cs index 3e8f75ac91..d2ca283a80 100644 --- a/NitroxClient/Communication/Packets/Processors/ExosuitArmActionProcessor.cs +++ b/NitroxClient/Communication/Packets/Processors/ExosuitArmActionProcessor.cs @@ -1,55 +1,39 @@ -using System; -using NitroxClient.Communication.Abstract; -using NitroxClient.Communication.Packets.Processors.Abstract; +using NitroxClient.Communication.Packets.Processors.Abstract; using NitroxClient.GameLogic; using NitroxClient.MonoBehaviours; using NitroxModel_Subnautica.DataStructures; -using NitroxModel.DataStructures.Util; using NitroxModel_Subnautica.Packets; using UnityEngine; -namespace NitroxClient.Communication.Packets.Processors +namespace NitroxClient.Communication.Packets.Processors; + +public class ExosuitArmActionProcessor : ClientPacketProcessor { - public class ExosuitArmActionProcessor : ClientPacketProcessor + public override void Process(ExosuitArmActionPacket packet) { - private readonly IPacketSender packetSender; - private readonly ExosuitModuleEvent exosuitModuleEvent; - - public ExosuitArmActionProcessor(IPacketSender packetSender, ExosuitModuleEvent exosuitModuleEvent) + if (!NitroxEntity.TryGetObjectFrom(packet.ArmId, out GameObject gameObject)) { - this.packetSender = packetSender; - this.exosuitModuleEvent = exosuitModuleEvent; + Log.Error("Could not find exosuit arm"); + return; } - public override void Process(ExosuitArmActionPacket packet) + switch (packet.TechType) { - Optional opGameObject = NitroxEntity.GetObjectFrom(packet.ArmId); - if (!opGameObject.HasValue) - { - Log.Error("Could not find exosuit arm"); - return; - } - GameObject gameObject = opGameObject.Value; - switch (packet.TechType) - { - - case TechType.ExosuitClawArmModule: - exosuitModuleEvent.UseClaw(gameObject.GetComponent(), packet.ArmAction); - break; - case TechType.ExosuitDrillArmModule: - exosuitModuleEvent.UseDrill(gameObject.GetComponent(), packet.ArmAction); - break; - case TechType.ExosuitGrapplingArmModule: - exosuitModuleEvent.UseGrappling(gameObject.GetComponent(), packet.ArmAction, packet.OpVector?.ToUnity()); - break; - case TechType.ExosuitTorpedoArmModule: - exosuitModuleEvent.UseTorpedo(gameObject.GetComponent(), packet.ArmAction, packet.OpVector?.ToUnity(), packet.OpRotation?.ToUnity()); - break; - default: - Log.Error($"Got an arm tech that is not handled: {packet.TechType} with action: {packet.ArmAction} for id {packet.ArmId}"); - break; - } - + case TechType.ExosuitClawArmModule: + ExosuitModuleEvent.UseClaw(gameObject.GetComponent(), packet.ArmAction); + break; + case TechType.ExosuitDrillArmModule: + ExosuitModuleEvent.UseDrill(gameObject.GetComponent(), packet.ArmAction); + break; + case TechType.ExosuitGrapplingArmModule: + ExosuitModuleEvent.UseGrappling(gameObject.GetComponent(), packet.ArmAction, packet.OpVector?.ToUnity()); + break; + case TechType.ExosuitTorpedoArmModule: + ExosuitModuleEvent.UseTorpedo(gameObject.GetComponent(), packet.ArmAction, packet.OpVector?.ToUnity(), packet.OpRotation?.ToUnity()); + break; + default: + Log.Error($"Got an arm tech that is not handled: {packet.TechType} with action: {packet.ArmAction} for id {packet.ArmId}"); + break; } } } diff --git a/NitroxClient/Communication/Packets/Processors/FMODAssetProcessor.cs b/NitroxClient/Communication/Packets/Processors/FMODAssetProcessor.cs new file mode 100644 index 0000000000..9383c94c71 --- /dev/null +++ b/NitroxClient/Communication/Packets/Processors/FMODAssetProcessor.cs @@ -0,0 +1,28 @@ +using NitroxClient.Communication.Packets.Processors.Abstract; +using NitroxClient.MonoBehaviours; +using NitroxModel_Subnautica.DataStructures; +using NitroxModel.GameLogic.FMOD; +using NitroxModel.Packets; + +namespace NitroxClient.Communication.Packets.Processors; + +public class FMODAssetProcessor : ClientPacketProcessor +{ + private readonly FMODWhitelist fmodWhitelist; + + public FMODAssetProcessor(FMODWhitelist fmodWhitelist) + { + this.fmodWhitelist = fmodWhitelist; + } + + public override void Process(FMODAssetPacket packet) + { + if (!fmodWhitelist.TryGetSoundData(packet.AssetPath, out SoundData soundData)) + { + Log.ErrorOnce($"[{nameof(FMODAssetProcessor)}] Whitelist has no item for {packet.AssetPath}."); + return; + } + + FMODEmitterController.PlayEventOneShot(packet.AssetPath, soundData.Radius, packet.Position.ToUnity(), packet.Volume); + } +} diff --git a/NitroxClient/Communication/Packets/Processors/FMODCustomEmitterProcessor.cs b/NitroxClient/Communication/Packets/Processors/FMODCustomEmitterProcessor.cs new file mode 100644 index 0000000000..e40390b03e --- /dev/null +++ b/NitroxClient/Communication/Packets/Processors/FMODCustomEmitterProcessor.cs @@ -0,0 +1,37 @@ +using NitroxClient.Communication.Packets.Processors.Abstract; +using NitroxClient.MonoBehaviours; +using NitroxModel.Packets; +using UnityEngine; + +namespace NitroxClient.Communication.Packets.Processors; + +public class FMODCustomEmitterProcessor : ClientPacketProcessor +{ + public override void Process(FMODCustomEmitterPacket packet) + { + if (!NitroxEntity.TryGetObjectFrom(packet.Id, out GameObject emitterControllerEntity)) + { + Log.ErrorOnce($"[{nameof(FMODCustomEmitterProcessor)}] Couldn't find entity {packet.Id}"); + return; + } + + if (!emitterControllerEntity.TryGetComponent(out FMODEmitterController fmodEmitterController)) + { + fmodEmitterController = emitterControllerEntity.AddComponent(); + fmodEmitterController.LateRegisterEmitter(); + } + + using (PacketSuppressor.Suppress()) + using (PacketSuppressor.Suppress()) + { + if (packet.Play) + { + fmodEmitterController.PlayCustomEmitter(packet.AssetPath); + } + else + { + fmodEmitterController.StopCustomEmitter(packet.AssetPath); + } + } + } +} diff --git a/NitroxClient/Communication/Packets/Processors/FMODCustomLoopingEmitterProcessor.cs b/NitroxClient/Communication/Packets/Processors/FMODCustomLoopingEmitterProcessor.cs new file mode 100644 index 0000000000..ffae2f924c --- /dev/null +++ b/NitroxClient/Communication/Packets/Processors/FMODCustomLoopingEmitterProcessor.cs @@ -0,0 +1,26 @@ +using NitroxClient.Communication.Packets.Processors.Abstract; +using NitroxClient.MonoBehaviours; +using NitroxModel.Packets; +using UnityEngine; + +namespace NitroxClient.Communication.Packets.Processors; + +public class FMODCustomLoopingEmitterProcessor : ClientPacketProcessor +{ + public override void Process(FMODCustomLoopingEmitterPacket packet) + { + if (!NitroxEntity.TryGetObjectFrom(packet.Id, out GameObject emitterControllerObject)) + { + Log.ErrorOnce($"[{nameof(FMODCustomLoopingEmitterProcessor)}] Couldn't find entity {packet.Id}"); + return; + } + + if (!emitterControllerObject.TryGetComponent(out FMODEmitterController fmodEmitterController)) + { + fmodEmitterController = emitterControllerObject.AddComponent(); + fmodEmitterController.LateRegisterEmitter(); + } + + fmodEmitterController.PlayCustomLoopingEmitter(packet.AssetPath); + } +} diff --git a/NitroxClient/Communication/Packets/Processors/FMODEventInstanceProcessor.cs b/NitroxClient/Communication/Packets/Processors/FMODEventInstanceProcessor.cs new file mode 100644 index 0000000000..c31ba32846 --- /dev/null +++ b/NitroxClient/Communication/Packets/Processors/FMODEventInstanceProcessor.cs @@ -0,0 +1,33 @@ +using NitroxClient.Communication.Packets.Processors.Abstract; +using NitroxClient.MonoBehaviours; +using NitroxModel.Packets; +using UnityEngine; + +namespace NitroxClient.Communication.Packets.Processors; + +public class FMODEventInstanceProcessor : ClientPacketProcessor +{ + public override void Process(FMODEventInstancePacket packet) + { + if (!NitroxEntity.TryGetObjectFrom(packet.Id, out GameObject emitterControllerObject)) + { + Log.ErrorOnce($"[{nameof(FMODEventInstanceProcessor)}] Couldn't find entity {packet.Id}"); + return; + } + + if (!emitterControllerObject.TryGetComponent(out FMODEmitterController fmodEmitterController)) + { + fmodEmitterController = emitterControllerObject.AddComponent(); + fmodEmitterController.LateRegisterEmitter(); + } + + if (packet.Play) + { + fmodEmitterController.PlayEventInstance(packet.AssetPath, packet.Volume); + } + else + { + fmodEmitterController.StopEventInstance(packet.AssetPath); + } + } +} diff --git a/NitroxClient/Communication/Packets/Processors/FMODStudioEventEmitterProcessor.cs b/NitroxClient/Communication/Packets/Processors/FMODStudioEventEmitterProcessor.cs new file mode 100644 index 0000000000..a10ee34d12 --- /dev/null +++ b/NitroxClient/Communication/Packets/Processors/FMODStudioEventEmitterProcessor.cs @@ -0,0 +1,36 @@ +using NitroxClient.Communication.Packets.Processors.Abstract; +using NitroxClient.MonoBehaviours; +using NitroxModel.Packets; +using UnityEngine; + +namespace NitroxClient.Communication.Packets.Processors; + +public class FMODStudioEventEmitterProcessor : ClientPacketProcessor +{ + public override void Process(FMODStudioEmitterPacket packet) + { + if (!NitroxEntity.TryGetObjectFrom(packet.Id, out GameObject emitterControllerObject)) + { + Log.ErrorOnce($"[{nameof(FMODStudioEventEmitterProcessor)}] Couldn't find entity {packet.Id}"); + return; + } + + if (!emitterControllerObject.TryGetComponent(out FMODEmitterController fmodEmitterController)) + { + fmodEmitterController = emitterControllerObject.AddComponent(); + fmodEmitterController.LateRegisterEmitter(); + } + + using (PacketSuppressor.Suppress()) + { + if (packet.Play) + { + fmodEmitterController.PlayStudioEmitter(packet.AssetPath); + } + else + { + fmodEmitterController.StopStudioEmitter(packet.AssetPath, packet.AllowFadeout); + } + } + } +} diff --git a/NitroxClient/Communication/Packets/Processors/GameModeChangedProcessor.cs b/NitroxClient/Communication/Packets/Processors/GameModeChangedProcessor.cs index 2132f8f012..228a425824 100644 --- a/NitroxClient/Communication/Packets/Processors/GameModeChangedProcessor.cs +++ b/NitroxClient/Communication/Packets/Processors/GameModeChangedProcessor.cs @@ -1,13 +1,40 @@ -using NitroxClient.Communication.Packets.Processors.Abstract; +using NitroxClient.Communication.Packets.Processors.Abstract; +using NitroxClient.GameLogic; using NitroxModel.Packets; -namespace NitroxClient.Communication.Packets.Processors +namespace NitroxClient.Communication.Packets.Processors; + +public class GameModeChangedProcessor : ClientPacketProcessor { - public class GameModeChangedProcessor : ClientPacketProcessor + private readonly LocalPlayer localPlayer; + private readonly PlayerManager playerManager; + + public GameModeChangedProcessor(LocalPlayer localPlayer, PlayerManager playerManager) + { + this.localPlayer = localPlayer; + this.playerManager = playerManager; + } + + public override void Process(GameModeChanged packet) { - public override void Process(GameModeChanged packet) + if (packet.AllPlayers || packet.PlayerId == localPlayer.PlayerId) { +#if SUBNAUTICA GameModeUtils.SetGameMode((GameModeOption)(int)packet.GameMode, GameModeOption.None); +#elif BELOWZERO + GameModeManager.SetGameOptions((GameModePresetId)(int)packet.GameMode); +#endif + } + if (packet.AllPlayers) + { + foreach (RemotePlayer remotePlayer in playerManager.GetAll()) + { + remotePlayer.SetGameMode(packet.GameMode); + } + } + else if (playerManager.TryFind(packet.PlayerId, out RemotePlayer remotePlayer)) + { + remotePlayer.SetGameMode(packet.GameMode); } } } diff --git a/NitroxClient/Communication/Packets/Processors/InitialPlayerSyncProcessor.cs b/NitroxClient/Communication/Packets/Processors/InitialPlayerSyncProcessor.cs index 0092035b2b..f53a28adb6 100644 --- a/NitroxClient/Communication/Packets/Processors/InitialPlayerSyncProcessor.cs +++ b/NitroxClient/Communication/Packets/Processors/InitialPlayerSyncProcessor.cs @@ -1,9 +1,9 @@ -using System; +using System; using System.Collections; using System.Collections.Generic; using NitroxClient.Communication.Abstract; using NitroxClient.Communication.Packets.Processors.Abstract; -using NitroxClient.GameLogic.InitialSync.Base; +using NitroxClient.GameLogic.InitialSync.Abstract; using NitroxClient.MonoBehaviours; using NitroxModel.Packets; @@ -12,8 +12,8 @@ namespace NitroxClient.Communication.Packets.Processors public class InitialPlayerSyncProcessor : ClientPacketProcessor { private readonly IPacketSender packetSender; - private readonly HashSet processors; - private readonly HashSet alreadyRan = new HashSet(); + private readonly HashSet processors; + private readonly HashSet alreadyRan = new(); private InitialPlayerSync packet; private WaitScreen.ManualWaitItem loadingMultiplayerWaitItem; @@ -22,7 +22,7 @@ public class InitialPlayerSyncProcessor : ClientPacketProcessor processors) + public InitialPlayerSyncProcessor(IPacketSender packetSender, IEnumerable processors) { this.packetSender = packetSender; this.processors = processors.ToSet(); @@ -38,21 +38,17 @@ public override void Process(InitialPlayerSync packet) private IEnumerator ProcessInitialSyncPacket(object sender, EventArgs eventArgs) { - // Some packets should not fire during game session join but only afterwards so that initialized/spawned game objects don't trigger packet sending again. - using (PacketSuppressor.Suppress()) + bool moreProcessorsToRun; + do { - bool moreProcessorsToRun; - do + yield return Multiplayer.Main.StartCoroutine(RunPendingProcessors()); + + moreProcessorsToRun = alreadyRan.Count < processors.Count; + if (moreProcessorsToRun && processorsRanLastCycle == 0) { - yield return Multiplayer.Main.StartCoroutine(RunPendingProcessors()); - - moreProcessorsToRun = alreadyRan.Count < processors.Count; - if (moreProcessorsToRun && processorsRanLastCycle == 0) - { - throw new Exception($"Detected circular dependencies in initial packet sync between: {GetRemainingProcessorsText()}"); - } - } while (moreProcessorsToRun); - } + throw new Exception($"Detected circular dependencies in initial packet sync between: {GetRemainingProcessorsText()}"); + } + } while (moreProcessorsToRun); WaitScreen.Remove(loadingMultiplayerWaitItem); Multiplayer.Main.InitialSyncCompleted = true; @@ -68,17 +64,17 @@ private IEnumerator RunPendingProcessors() { processorsRanLastCycle = 0; - foreach (InitialSyncProcessor processor in processors) + foreach (IInitialSyncProcessor processor in processors) { if (IsWaitingToRun(processor.GetType()) && HasDependenciesSatisfied(processor)) { loadingMultiplayerWaitItem.SetProgress(cumulativeProcessorsRan, processors.Count); - Log.Info($"Running {processor.GetType()}"); alreadyRan.Add(processor.GetType()); processorsRanLastCycle++; cumulativeProcessorsRan++; + Log.Info($"Running {processor.GetType()}"); subWaitScreenItem = WaitScreen.Add($"Running {processor.GetType().Name}"); yield return Multiplayer.Main.StartCoroutine(processor.Process(packet, subWaitScreenItem)); WaitScreen.Remove(subWaitScreenItem); @@ -86,7 +82,7 @@ private IEnumerator RunPendingProcessors() } } - private bool HasDependenciesSatisfied(InitialSyncProcessor processor) + private bool HasDependenciesSatisfied(IInitialSyncProcessor processor) { foreach (Type dependentType in processor.DependentProcessors) { @@ -108,7 +104,7 @@ private string GetRemainingProcessorsText() { string remaining = ""; - foreach (InitialSyncProcessor processor in processors) + foreach (IInitialSyncProcessor processor in processors) { if (IsWaitingToRun(processor.GetType())) { diff --git a/NitroxClient/Communication/Packets/Processors/LeakRepairedProcessor.cs b/NitroxClient/Communication/Packets/Processors/LeakRepairedProcessor.cs new file mode 100644 index 0000000000..886c54ca54 --- /dev/null +++ b/NitroxClient/Communication/Packets/Processors/LeakRepairedProcessor.cs @@ -0,0 +1,17 @@ +using NitroxClient.Communication.Packets.Processors.Abstract; +using NitroxClient.MonoBehaviours; +using NitroxModel.Packets; +using NitroxModel_Subnautica.DataStructures; + +namespace NitroxClient.Communication.Packets.Processors; + +public class LeakRepairedProcessor : ClientPacketProcessor +{ + public override void Process(LeakRepaired packet) + { + if (NitroxEntity.TryGetComponentFrom(packet.BaseId, out BaseLeakManager baseLeakManager)) + { + baseLeakManager.HealLeakToMax(packet.RelativeCell.ToUnity()); + } + } +} diff --git a/NitroxClient/Communication/Packets/Processors/MedicalCabinetClickedProcessor.cs b/NitroxClient/Communication/Packets/Processors/MedicalCabinetClickedProcessor.cs index e3493d2398..43e82a4f39 100644 --- a/NitroxClient/Communication/Packets/Processors/MedicalCabinetClickedProcessor.cs +++ b/NitroxClient/Communication/Packets/Processors/MedicalCabinetClickedProcessor.cs @@ -1,4 +1,3 @@ -using NitroxClient.Communication.Abstract; using NitroxClient.Communication.Packets.Processors.Abstract; using NitroxClient.GameLogic.FMOD; using NitroxClient.MonoBehaviours; @@ -10,13 +9,6 @@ namespace NitroxClient.Communication.Packets.Processors; public class MedicalCabinetClickedProcessor : ClientPacketProcessor { - private readonly IPacketSender packetSender; - - public MedicalCabinetClickedProcessor(IPacketSender packetSender) - { - this.packetSender = packetSender; - } - public override void Process(MedicalCabinetClicked packet) { GameObject gameObject = NitroxEntity.RequireObjectFrom(packet.Id); @@ -28,8 +20,8 @@ public override void Process(MedicalCabinetClicked packet) cabinet.hasMedKit = packet.HasMedKit; cabinet.timeSpawnMedKit = packet.NextSpawnTime; - using (PacketSuppressor.Suppress()) - using (FMODSystem.SuppressSounds()) + using (PacketSuppressor.Suppress()) + using (FMODSystem.SuppressSubnauticaSounds()) { if (doorChangedState) { diff --git a/NitroxClient/Communication/Packets/Processors/PDAEncyclopediaEntryAddProcessor.cs b/NitroxClient/Communication/Packets/Processors/PDAEncyclopediaEntryAddProcessor.cs index e36a3e0da5..60d277b91f 100644 --- a/NitroxClient/Communication/Packets/Processors/PDAEncyclopediaEntryAddProcessor.cs +++ b/NitroxClient/Communication/Packets/Processors/PDAEncyclopediaEntryAddProcessor.cs @@ -17,7 +17,11 @@ public override void Process(PDAEncyclopediaEntryAdd packet) { using (PacketSuppressor.Suppress()) { +#if SUBNAUTICA PDAEncyclopedia.Add(packet.Key, packet.Verbose); +#elif BELOWZERO + PDAEncyclopedia.Add(packet.Key, packet.Verbose, packet.PostNotification); +#endif } } } diff --git a/NitroxClient/Communication/Packets/Processors/PDALogEntryAddProcessor.cs b/NitroxClient/Communication/Packets/Processors/PDALogEntryAddProcessor.cs index 1cdafcd64d..5fd14836d9 100644 --- a/NitroxClient/Communication/Packets/Processors/PDALogEntryAddProcessor.cs +++ b/NitroxClient/Communication/Packets/Processors/PDALogEntryAddProcessor.cs @@ -1,4 +1,4 @@ -using NitroxClient.Communication.Abstract; +using NitroxClient.Communication.Abstract; using NitroxClient.Communication.Packets.Processors.Abstract; using NitroxModel.Packets; @@ -17,7 +17,11 @@ public override void Process(PDALogEntryAdd packet) { using (PacketSuppressor.Suppress()) { +#if SUBNAUTICA PDALog.Add(packet.Key); +#elif BELOWZERO + PDALog.Add(packet.Key, true); +#endif } } } diff --git a/NitroxClient/Communication/Packets/Processors/PingRenamedProcessor.cs b/NitroxClient/Communication/Packets/Processors/PingRenamedProcessor.cs deleted file mode 100644 index 3fc78c3f63..0000000000 --- a/NitroxClient/Communication/Packets/Processors/PingRenamedProcessor.cs +++ /dev/null @@ -1,49 +0,0 @@ -using NitroxClient.Communication.Abstract; -using NitroxClient.Communication.Packets.Processors.Abstract; -using NitroxClient.MonoBehaviours; -using NitroxModel.DataStructures.Util; -using NitroxModel.Packets; -using UnityEngine; - -namespace NitroxClient.Communication.Packets.Processors -{ - /// - /// Only syncs pings from beacons for now. - /// - public class PingRenamedProcessor : ClientPacketProcessor - { - private readonly IPacketSender sender; - - public PingRenamedProcessor(IPacketSender sender) - { - this.sender = sender; - } - - public override void Process(PingRenamed packet) - { - Optional obj = NitroxEntity.GetObjectFrom(packet.Id); - if (!obj.HasValue) - { - // Not the object we're looking for. - return; - } - Beacon beacon = obj.Value.GetComponent(); - if (!beacon) - { - // This can be ok if origin of ping instance component was not from a beacon (but from signal or other). - return; - } - if (beacon.GetComponent()) - { - // Skip over beacon component on player GameObjects - return; - } - - using (PacketSuppressor.Suppress()) - { - beacon.beaconLabel.SetLabel(packet.Name); - Log.Debug($"Received ping rename: '{packet.Name}' on object '{obj.Value.GetFullHierarchyPath()}' with Nitrox id: '{packet.Id}'"); - } - } - } -} diff --git a/NitroxClient/Communication/Packets/Processors/PlaceBasePieceProcessor.cs b/NitroxClient/Communication/Packets/Processors/PlaceBasePieceProcessor.cs deleted file mode 100644 index cedd4a7f98..0000000000 --- a/NitroxClient/Communication/Packets/Processors/PlaceBasePieceProcessor.cs +++ /dev/null @@ -1,21 +0,0 @@ -using NitroxClient.Communication.Packets.Processors.Abstract; -using NitroxClient.GameLogic.Bases; -using NitroxModel.Packets; - -namespace NitroxClient.Communication.Packets.Processors -{ - public class PlaceBasePieceProcessor : ClientPacketProcessor - { - private BuildThrottlingQueue buildEventQueue; - - public PlaceBasePieceProcessor(BuildThrottlingQueue buildEventQueue) - { - this.buildEventQueue = buildEventQueue; - } - - public override void Process(PlaceBasePiece packet) - { - buildEventQueue.EnqueueBasePiecePlaced(packet.BasePiece); - } - } -} diff --git a/NitroxClient/Communication/Packets/Processors/PlayFMODAssetProcessor.cs b/NitroxClient/Communication/Packets/Processors/PlayFMODAssetProcessor.cs deleted file mode 100644 index 4c565a84e2..0000000000 --- a/NitroxClient/Communication/Packets/Processors/PlayFMODAssetProcessor.cs +++ /dev/null @@ -1,27 +0,0 @@ -using FMOD.Studio; -using FMODUnity; -using NitroxClient.Communication.Packets.Processors.Abstract; -using NitroxModel.Packets; -using NitroxModel_Subnautica.DataStructures; -using UnityEngine; - -#pragma warning disable 618 - -namespace NitroxClient.Communication.Packets.Processors -{ - public class PlayFMODAssetProcessor : ClientPacketProcessor - { - public override void Process(PlayFMODAsset packet) - { - EventInstance instance = FMODUWE.GetEvent(packet.AssetPath); - instance.setProperty(EVENT_PROPERTY.MINIMUM_DISTANCE, 1f); - instance.setProperty(EVENT_PROPERTY.MAXIMUM_DISTANCE, packet.Radius); - // Volume is a scalar, is should be limited to 0 and we don't need more than 100% volume (i.e. 1.0). - // See docs: https://fmod.com/resources/documentation-api?version=2.00&page=studio-api-eventinstance.html#studio_eventinstance_setvolume - instance.setVolume(Mathf.Clamp01(packet.Volume)); - instance.set3DAttributes(packet.Position.ToUnity().To3DAttributes()); - instance.start(); - instance.release(); - } - } -} diff --git a/NitroxClient/Communication/Packets/Processors/PlayFMODCustomEmitterProcessor.cs b/NitroxClient/Communication/Packets/Processors/PlayFMODCustomEmitterProcessor.cs deleted file mode 100644 index 4449dcaaac..0000000000 --- a/NitroxClient/Communication/Packets/Processors/PlayFMODCustomEmitterProcessor.cs +++ /dev/null @@ -1,38 +0,0 @@ -using NitroxClient.Communication.Abstract; -using NitroxClient.Communication.Packets.Processors.Abstract; -using NitroxClient.MonoBehaviours; -using NitroxClient.Unity.Helper; -using NitroxModel.Packets; -using UnityEngine; - -namespace NitroxClient.Communication.Packets.Processors; - -public class PlayFMODCustomEmitterProcessor : ClientPacketProcessor -{ - private readonly IPacketSender packetSender; - - public PlayFMODCustomEmitterProcessor(IPacketSender packetSender) - { - this.packetSender = packetSender; - } - - - public override void Process(PlayFMODCustomEmitter packet) - { - GameObject soundSource = NitroxEntity.RequireObjectFrom(packet.Id); - FMODEmitterController fmodEmitterController = soundSource.RequireComponent(); - - using (PacketSuppressor.Suppress()) - using (PacketSuppressor.Suppress()) - { - if (packet.Play) - { - fmodEmitterController.PlayCustomEmitter(packet.AssetPath); - } - else - { - fmodEmitterController.StopCustomEmitter(packet.AssetPath); - } - } - } -} diff --git a/NitroxClient/Communication/Packets/Processors/PlayFMODCustomLoopingEmitterProcessor.cs b/NitroxClient/Communication/Packets/Processors/PlayFMODCustomLoopingEmitterProcessor.cs deleted file mode 100644 index c0bb67ace5..0000000000 --- a/NitroxClient/Communication/Packets/Processors/PlayFMODCustomLoopingEmitterProcessor.cs +++ /dev/null @@ -1,18 +0,0 @@ -using NitroxClient.Communication.Packets.Processors.Abstract; -using NitroxClient.MonoBehaviours; -using NitroxClient.Unity.Helper; -using NitroxModel.Packets; -using UnityEngine; - -namespace NitroxClient.Communication.Packets.Processors; - -public class PlayFMODCustomLoopingEmitterProcessor : ClientPacketProcessor -{ - public override void Process(PlayFMODCustomLoopingEmitter packet) - { - GameObject soundSource = NitroxEntity.RequireObjectFrom(packet.Id); - FMODEmitterController fmodEmitterController = soundSource.RequireComponent(); - - fmodEmitterController.PlayCustomLoopingEmitter(packet.AssetPath); - } -} diff --git a/NitroxClient/Communication/Packets/Processors/PlayFMODStudioEventEmitterProcessor.cs b/NitroxClient/Communication/Packets/Processors/PlayFMODStudioEventEmitterProcessor.cs deleted file mode 100644 index e18398a8fc..0000000000 --- a/NitroxClient/Communication/Packets/Processors/PlayFMODStudioEventEmitterProcessor.cs +++ /dev/null @@ -1,37 +0,0 @@ -using NitroxClient.Communication.Abstract; -using NitroxClient.Communication.Packets.Processors.Abstract; -using NitroxClient.MonoBehaviours; -using NitroxClient.Unity.Helper; -using NitroxModel.Packets; -using UnityEngine; - -namespace NitroxClient.Communication.Packets.Processors; - -public class PlayFMODStudioEventEmitterProcessor : ClientPacketProcessor -{ - private readonly IPacketSender packetSender; - - public PlayFMODStudioEventEmitterProcessor(IPacketSender packetSender) - { - this.packetSender = packetSender; - } - - - public override void Process(PlayFMODStudioEmitter packet) - { - GameObject soundSource = NitroxEntity.RequireObjectFrom(packet.Id); - FMODEmitterController fmodEmitterController = soundSource.RequireComponent(); - - using (PacketSuppressor.Suppress()) - { - if (packet.Play) - { - fmodEmitterController.PlayStudioEmitter(packet.AssetPath); - } - else - { - fmodEmitterController.StopStudioEmitter(packet.AssetPath, packet.AllowFadeout); - } - } - } -} diff --git a/NitroxClient/Communication/Packets/Processors/PlayerCinematicControllerCallProcessor.cs b/NitroxClient/Communication/Packets/Processors/PlayerCinematicControllerCallProcessor.cs index ac97d22b3a..c1d65d4aa2 100644 --- a/NitroxClient/Communication/Packets/Processors/PlayerCinematicControllerCallProcessor.cs +++ b/NitroxClient/Communication/Packets/Processors/PlayerCinematicControllerCallProcessor.cs @@ -1,7 +1,7 @@ -using NitroxClient.Communication.Packets.Processors.Abstract; +using NitroxClient.Communication.Packets.Processors.Abstract; using NitroxClient.GameLogic; using NitroxClient.MonoBehaviours; -using NitroxClient.MonoBehaviours.Overrides; +using NitroxClient.MonoBehaviours.CinematicController; using NitroxModel.DataStructures.Util; using NitroxModel.Helper; using NitroxModel.Packets; @@ -20,11 +20,16 @@ public PlayerCinematicControllerCallProcessor(PlayerManager playerManager) public override void Process(PlayerCinematicControllerCall packet) { - Optional opEntity = NitroxEntity.GetObjectFrom(packet.ControllerID); - Validate.IsPresent(opEntity); + if (!NitroxEntity.TryGetObjectFrom(packet.ControllerID, out GameObject entity)) + { + return; // Entity can be not spawned yet bc async. + } - MultiplayerCinematicReference reference = opEntity.Value.GetComponent(); - Validate.IsTrue(reference); + if (!entity.TryGetComponent(out MultiplayerCinematicReference reference)) + { + Log.Warn($"Couldn't find {nameof(MultiplayerCinematicReference)} on {entity.name}:{packet.ControllerID}"); + return; + } Optional opPlayer = playerManager.Find(packet.PlayerId); Validate.IsPresent(opPlayer); diff --git a/NitroxClient/Communication/Packets/Processors/PlayerDeathProcessor.cs b/NitroxClient/Communication/Packets/Processors/PlayerDeathProcessor.cs index 977c1b1807..981ebe24bb 100644 --- a/NitroxClient/Communication/Packets/Processors/PlayerDeathProcessor.cs +++ b/NitroxClient/Communication/Packets/Processors/PlayerDeathProcessor.cs @@ -17,9 +17,10 @@ public PlayerDeathProcessor(PlayerManager playerManager) public override void Process(PlayerDeathEvent playerDeath) { RemotePlayer player = Validate.IsPresent(playerManager.Find(playerDeath.PlayerId)); - Log.InGame($"{player.PlayerName} died"); + Log.Debug($"{player.PlayerName} died"); + Log.InGame(Language.main.Get("Nitrox_PlayerDied").Replace("{PLAYER}", player.PlayerName)); player.PlayerDeathEvent.Trigger(player); - + // TODO: Add any death related triggers (i.e. scoreboard updates, rewards, etc.) } } diff --git a/NitroxClient/Communication/Packets/Processors/PlayerHeldItemChangedProcessor.cs b/NitroxClient/Communication/Packets/Processors/PlayerHeldItemChangedProcessor.cs index 28ac82a8b5..3e61db7431 100644 --- a/NitroxClient/Communication/Packets/Processors/PlayerHeldItemChangedProcessor.cs +++ b/NitroxClient/Communication/Packets/Processors/PlayerHeldItemChangedProcessor.cs @@ -1,5 +1,4 @@ using System; -using System.Reflection; using NitroxClient.Communication.Packets.Processors.Abstract; using NitroxClient.GameLogic; using NitroxClient.MonoBehaviours; @@ -8,112 +7,113 @@ using NitroxModel.Packets; using UnityEngine; -namespace NitroxClient.Communication.Packets.Processors +namespace NitroxClient.Communication.Packets.Processors; + +public class PlayerHeldItemChangedProcessor : ClientPacketProcessor { - public class PlayerHeldItemChangedProcessor : ClientPacketProcessor + private int defaultLayer; + private int viewModelLayer; + private readonly PlayerManager playerManager; + + public PlayerHeldItemChangedProcessor(PlayerManager playerManager) { - private int defaultLayer; - private int viewModelLayer; - private readonly PlayerManager playerManager; + this.playerManager = playerManager; - public PlayerHeldItemChangedProcessor(PlayerManager playerManager) + if (NitroxEnvironment.IsNormal) { - this.playerManager = playerManager; - - if (NitroxEnvironment.IsNormal) - { - SetupLayers(); - } + SetupLayers(); } + } + + private void SetupLayers() + { + defaultLayer = LayerMask.NameToLayer("Default"); + viewModelLayer = LayerMask.NameToLayer("Viewmodel"); + } + + public override void Process(PlayerHeldItemChanged packet) + { + Optional opPlayer = playerManager.Find(packet.PlayerId); + Validate.IsPresent(opPlayer); - private void SetupLayers() + if (!NitroxEntity.TryGetObjectFrom(packet.ItemId, out GameObject item)) { - defaultLayer = LayerMask.NameToLayer("Default"); - viewModelLayer = LayerMask.NameToLayer("Viewmodel"); + return; // Item can be not spawned yet bc async. } - public override void Process(PlayerHeldItemChanged packet) + Pickupable pickupable = item.GetComponent(); + Validate.IsTrue(pickupable); + + Validate.NotNull(pickupable.inventoryItem); + + ItemsContainer inventory = opPlayer.Value.Inventory; + PlayerTool tool = item.GetComponent(); + + // Copied from QuickSlots + switch (packet.Type) { - Optional opPlayer = playerManager.Find(packet.PlayerId); - Validate.IsPresent(opPlayer); - - Optional opItem = NitroxEntity.GetObjectFrom(packet.ItemId); - Validate.IsPresent(opItem); - - Pickupable pickupable = opItem.Value.GetComponent(); - Validate.IsTrue(pickupable); - - Validate.NotNull(pickupable.inventoryItem); - - ItemsContainer inventory = opPlayer.Value.Inventory; - PlayerTool tool = opItem.Value.GetComponent(); - - // Copied from QuickSlots - switch (packet.Type) - { - case PlayerHeldItemChanged.ChangeType.DRAW_AS_TOOL: - Validate.IsTrue(tool); - ModelPlug.PlugIntoSocket(tool, opPlayer.Value.ItemAttachPoint); - Utils.SetLayerRecursively(opItem.Value, viewModelLayer); - foreach (Animator componentsInChild in tool.GetComponentsInChildren()) - { - componentsInChild.cullingMode = AnimatorCullingMode.AlwaysAnimate; - } - if (tool.mainCollider) - { - tool.mainCollider.enabled = false; - } - tool.GetComponent().isKinematic = true; - opItem.Value.SetActive(true); - tool.SetHandIKTargetsEnabled(true); - SafeAnimator.SetBool(opPlayer.Value.ArmsController.GetComponent(), $"holding_{tool.animToolName}", true); - opPlayer.Value.AnimationController["using_tool_first"] = packet.IsFirstTime == null; - - if (opItem.Value.TryGetComponent(out FPModel fpModelDraw)) //FPModel needs to be updated - { - fpModelDraw.OnEquip(null, null); - } - break; - - case PlayerHeldItemChanged.ChangeType.HOLSTER_AS_TOOL: - Validate.IsTrue(tool); - opItem.Value.SetActive(false); - Utils.SetLayerRecursively(opItem.Value, defaultLayer); - if (tool.mainCollider) - { - tool.mainCollider.enabled = true; - } - tool.GetComponent().isKinematic = false; - pickupable.inventoryItem.item.Reparent(inventory.tr); - foreach (Animator componentsInChild in tool.GetComponentsInChildren()) - { - componentsInChild.cullingMode = AnimatorCullingMode.CullUpdateTransforms; - } - SafeAnimator.SetBool(opPlayer.Value.ArmsController.GetComponent(), $"holding_{tool.animToolName}", false); - opPlayer.Value.AnimationController["using_tool_first"] = false; - - if (opItem.Value.TryGetComponent(out FPModel fpModelHolster)) //FPModel needs to be updated - { - fpModelHolster.OnUnequip(null, null); - } - - break; - - case PlayerHeldItemChanged.ChangeType.DRAW_AS_ITEM: - pickupable.inventoryItem.item.Reparent(opPlayer.Value.ItemAttachPoint); - pickupable.inventoryItem.item.SetVisible(true); - Utils.SetLayerRecursively(pickupable.inventoryItem.item.gameObject, viewModelLayer); - break; - - case PlayerHeldItemChanged.ChangeType.HOLSTER_AS_ITEM: - pickupable.inventoryItem.item.Reparent(inventory.tr); - pickupable.inventoryItem.item.SetVisible(false); - Utils.SetLayerRecursively(pickupable.inventoryItem.item.gameObject, defaultLayer); - break; - - default: - throw new ArgumentOutOfRangeException(); - } + case PlayerHeldItemChanged.ChangeType.DRAW_AS_TOOL: + Validate.IsTrue(tool); + ModelPlug.PlugIntoSocket(tool, opPlayer.Value.ItemAttachPoint); + Utils.SetLayerRecursively(item, viewModelLayer); + foreach (Animator componentsInChild in tool.GetComponentsInChildren()) + { + componentsInChild.cullingMode = AnimatorCullingMode.AlwaysAnimate; + } + if (tool.mainCollider) + { + tool.mainCollider.enabled = false; + } + tool.GetComponent().isKinematic = true; + item.SetActive(true); + tool.SetHandIKTargetsEnabled(true); + SafeAnimator.SetBool(opPlayer.Value.ArmsController.GetComponent(), $"holding_{tool.animToolName}", true); + opPlayer.Value.AnimationController["using_tool_first"] = packet.IsFirstTime == null; + + if (item.TryGetComponent(out FPModel fpModelDraw)) //FPModel needs to be updated + { + fpModelDraw.OnEquip(null, null); + } + break; + + case PlayerHeldItemChanged.ChangeType.HOLSTER_AS_TOOL: + Validate.IsTrue(tool); + item.SetActive(false); + Utils.SetLayerRecursively(item, defaultLayer); + if (tool.mainCollider) + { + tool.mainCollider.enabled = true; + } + tool.GetComponent().isKinematic = false; + pickupable.inventoryItem.item.Reparent(inventory.tr); + foreach (Animator componentsInChild in tool.GetComponentsInChildren()) + { + componentsInChild.cullingMode = AnimatorCullingMode.CullUpdateTransforms; + } + SafeAnimator.SetBool(opPlayer.Value.ArmsController.GetComponent(), $"holding_{tool.animToolName}", false); + opPlayer.Value.AnimationController["using_tool_first"] = false; + + if (item.TryGetComponent(out FPModel fpModelHolster)) //FPModel needs to be updated + { + fpModelHolster.OnUnequip(null, null); + } + + break; + + case PlayerHeldItemChanged.ChangeType.DRAW_AS_ITEM: + pickupable.inventoryItem.item.Reparent(opPlayer.Value.ItemAttachPoint); + pickupable.inventoryItem.item.SetVisible(true); + Utils.SetLayerRecursively(pickupable.inventoryItem.item.gameObject, viewModelLayer); + break; + + case PlayerHeldItemChanged.ChangeType.HOLSTER_AS_ITEM: + pickupable.inventoryItem.item.Reparent(inventory.tr); + pickupable.inventoryItem.item.SetVisible(false); + Utils.SetLayerRecursively(pickupable.inventoryItem.item.gameObject, defaultLayer); + break; + + default: + throw new ArgumentOutOfRangeException(nameof(packet.Type)); } } } diff --git a/NitroxClient/Communication/Packets/Processors/PlayerJoinedMultiplayerSessionProcessor.cs b/NitroxClient/Communication/Packets/Processors/PlayerJoinedMultiplayerSessionProcessor.cs index b37cbab008..e35308fe8b 100644 --- a/NitroxClient/Communication/Packets/Processors/PlayerJoinedMultiplayerSessionProcessor.cs +++ b/NitroxClient/Communication/Packets/Processors/PlayerJoinedMultiplayerSessionProcessor.cs @@ -1,30 +1,33 @@ -using System.Collections.Generic; -using System.Linq; +using System.Collections; using NitroxClient.Communication.Packets.Processors.Abstract; using NitroxClient.GameLogic; using NitroxModel.Packets; -using NitroxModel_Subnautica.DataStructures; +using UWE; -namespace NitroxClient.Communication.Packets.Processors -{ - public class PlayerJoinedMultiplayerSessionProcessor : ClientPacketProcessor - { - private readonly PlayerManager playerManager; +namespace NitroxClient.Communication.Packets.Processors; - public PlayerJoinedMultiplayerSessionProcessor(PlayerManager playerManager) - { - this.playerManager = playerManager; - } +public class PlayerJoinedMultiplayerSessionProcessor : ClientPacketProcessor +{ + private readonly PlayerManager playerManager; + private readonly Entities entities; - public override void Process(PlayerJoinedMultiplayerSession packet) - { - List techTypes = packet.EquippedTechTypes.Select(techType => techType.ToUnity()).ToList(); - List items = new List(); + public PlayerJoinedMultiplayerSessionProcessor(PlayerManager playerManager, Entities entities) + { + this.playerManager = playerManager; + this.entities = entities; + } - playerManager.Create(packet.PlayerContext); + public override void Process(PlayerJoinedMultiplayerSession packet) + { + CoroutineHost.StartCoroutine(SpawnRemotePlayer(packet)); + } - Log.InGame(Language.main.Get("Nitrox_PlayerJoined").Replace("{PLAYER}", packet.PlayerContext.PlayerName)); + private IEnumerator SpawnRemotePlayer(PlayerJoinedMultiplayerSession packet) + { + playerManager.Create(packet.PlayerContext); + yield return entities.SpawnEntityAsync(packet.PlayerWorldEntity, true, true); - } + Log.Info($"{packet.PlayerContext.PlayerName} joined the game"); + Log.InGame(Language.main.Get("Nitrox_PlayerJoined").Replace("{PLAYER}", packet.PlayerContext.PlayerName)); } } diff --git a/NitroxClient/Communication/Packets/Processors/PlayerKickedProcessor.cs b/NitroxClient/Communication/Packets/Processors/PlayerKickedProcessor.cs index 9ca21ff20f..c7500bd701 100644 --- a/NitroxClient/Communication/Packets/Processors/PlayerKickedProcessor.cs +++ b/NitroxClient/Communication/Packets/Processors/PlayerKickedProcessor.cs @@ -1,6 +1,6 @@ using NitroxClient.Communication.Abstract; using NitroxClient.Communication.Packets.Processors.Abstract; -using NitroxClient.MonoBehaviours.Gui.InGame; +using NitroxClient.MonoBehaviours.Gui.Modals; using NitroxModel.Packets; namespace NitroxClient.Communication.Packets.Processors diff --git a/NitroxClient/Communication/Packets/Processors/PlayerStatsProcessor.cs b/NitroxClient/Communication/Packets/Processors/PlayerStatsProcessor.cs index e5dfc36077..0551db0e42 100644 --- a/NitroxClient/Communication/Packets/Processors/PlayerStatsProcessor.cs +++ b/NitroxClient/Communication/Packets/Processors/PlayerStatsProcessor.cs @@ -1,23 +1,23 @@ -using NitroxClient.Communication.Packets.Processors.Abstract; +using NitroxClient.Communication.Packets.Processors.Abstract; using NitroxClient.GameLogic.HUD; using NitroxClient.MonoBehaviours.Gui.HUD; using NitroxModel.Packets; -namespace NitroxClient.Communication.Packets.Processors +namespace NitroxClient.Communication.Packets.Processors; + +public class PlayerStatsProcessor : ClientPacketProcessor { - class PlayerStatsProcessor : ClientPacketProcessor - { - private readonly PlayerVitalsManager vitalsManager; + private readonly PlayerVitalsManager vitalsManager; - public PlayerStatsProcessor(PlayerVitalsManager vitalsManager) - { - this.vitalsManager = vitalsManager; - } + public PlayerStatsProcessor(PlayerVitalsManager vitalsManager) + { + this.vitalsManager = vitalsManager; + } - public override void Process(PlayerStats playerStats) + public override void Process(PlayerStats playerStats) + { + if (vitalsManager.TryFindForPlayer(playerStats.PlayerId, out RemotePlayerVitals vitals)) { - RemotePlayerVitals vitals = vitalsManager.CreateForPlayer(playerStats.PlayerId); - vitals.SetOxygen(playerStats.Oxygen, playerStats.MaxOxygen); vitals.SetHealth(playerStats.Health); vitals.SetFood(playerStats.Food); diff --git a/NitroxClient/Communication/Packets/Processors/RemoveCreatureCorpseProcessor.cs b/NitroxClient/Communication/Packets/Processors/RemoveCreatureCorpseProcessor.cs new file mode 100644 index 0000000000..e4927bc072 --- /dev/null +++ b/NitroxClient/Communication/Packets/Processors/RemoveCreatureCorpseProcessor.cs @@ -0,0 +1,71 @@ +using System.Collections; +using NitroxClient.Communication.Packets.Processors.Abstract; +using NitroxClient.GameLogic; +using NitroxClient.MonoBehaviours; +using NitroxModel.DataStructures; +using NitroxModel.Packets; +using NitroxModel_Subnautica.DataStructures; +using UWE; + +namespace NitroxClient.Communication.Packets.Processors; + +public class RemoveCreatureCorpseProcessor : ClientPacketProcessor +{ + private readonly Entities entities; + private readonly LiveMixinManager liveMixinManager; + private readonly SimulationOwnership simulationOwnership; + + public RemoveCreatureCorpseProcessor(Entities entities, LiveMixinManager liveMixinManager, SimulationOwnership simulationOwnership) + { + this.entities = entities; + this.liveMixinManager = liveMixinManager; + this.simulationOwnership = simulationOwnership; + } + + public override void Process(RemoveCreatureCorpse packet) + { + entities.RemoveEntity(packet.CreatureId); + if (!NitroxEntity.TryGetComponentFrom(packet.CreatureId, out CreatureDeath creatureDeath)) + { + entities.MarkForDeletion(packet.CreatureId); + Log.Warn($"[{nameof(RemoveCreatureCorpseProcessor)}] Could not find entity with id: {packet.CreatureId} to remove corpse from."); + return; + } + + creatureDeath.transform.localPosition = packet.DeathPosition.ToUnity(); + creatureDeath.transform.localRotation = packet.DeathRotation.ToUnity(); + CoroutineHost.StartCoroutine(SimplerOnKillAsync(creatureDeath, packet.CreatureId)); + } + + /// + /// Calls only some parts from to avoid sending packets from it + /// or already synced behaviour (like spawning another respawner from the remote clients) + /// + public IEnumerator SimplerOnKillAsync(CreatureDeath creatureDeath, NitroxId creatureId) + { + // Ensure we don't broadcast anything from this kill event + simulationOwnership.StopSimulatingEntity(creatureId); + + // Remove the position broadcasting stuff from it + EntityPositionBroadcaster.RemoveEntityMovementControl(creatureDeath.gameObject, creatureId); + + // Receiving this packet means the creature is dead + liveMixinManager.SyncRemoteHealth(creatureDeath.liveMixin, 0); + + // To avoid SpawnRespawner to be called + creatureDeath.respawn = false; + creatureDeath.hasSpawnedRespawner = true; + + // To avoid the cooked data section + bool lastDamageWasHeat = creatureDeath.lastDamageWasHeat; + creatureDeath.lastDamageWasHeat = false; + + using (PacketSuppressor.Suppress()) + { + yield return creatureDeath.OnKillAsync(); + } + + // Restore the field in case it was useful + creatureDeath.lastDamageWasHeat = lastDamageWasHeat; + } +} diff --git a/NitroxClient/Communication/Packets/Processors/SeamothModuleActionProcessor.cs b/NitroxClient/Communication/Packets/Processors/SeamothModuleActionProcessor.cs index 55299f12b6..aad649c29d 100644 --- a/NitroxClient/Communication/Packets/Processors/SeamothModuleActionProcessor.cs +++ b/NitroxClient/Communication/Packets/Processors/SeamothModuleActionProcessor.cs @@ -1,4 +1,5 @@ -using NitroxClient.Communication.Abstract; +#if SUBNAUTICA +using NitroxClient.Communication.Abstract; using NitroxClient.Communication.Packets.Processors.Abstract; using NitroxClient.MonoBehaviours; using NitroxModel.Packets; @@ -79,3 +80,4 @@ public static bool TorpedoShot(ItemsContainer container, TorpedoType torpedoType } } } +#endif diff --git a/NitroxClient/Communication/Packets/Processors/ServerStoppedProcessor.cs b/NitroxClient/Communication/Packets/Processors/ServerStoppedProcessor.cs index 81bc534653..f7e70838b4 100644 --- a/NitroxClient/Communication/Packets/Processors/ServerStoppedProcessor.cs +++ b/NitroxClient/Communication/Packets/Processors/ServerStoppedProcessor.cs @@ -1,6 +1,6 @@ using NitroxClient.Communication.Abstract; using NitroxClient.Communication.Packets.Processors.Abstract; -using NitroxClient.MonoBehaviours.Gui.InGame; +using NitroxClient.MonoBehaviours.Gui.Modals; using NitroxModel.Packets; namespace NitroxClient.Communication.Packets.Processors; diff --git a/NitroxClient/Communication/Packets/Processors/SimulationOwnershipChangeProcessor.cs b/NitroxClient/Communication/Packets/Processors/SimulationOwnershipChangeProcessor.cs index d4141e0e08..19fbbd0b12 100644 --- a/NitroxClient/Communication/Packets/Processors/SimulationOwnershipChangeProcessor.cs +++ b/NitroxClient/Communication/Packets/Processors/SimulationOwnershipChangeProcessor.cs @@ -1,7 +1,5 @@ -using NitroxClient.Communication.Abstract; using NitroxClient.Communication.Packets.Processors.Abstract; using NitroxClient.GameLogic; -using NitroxClient.MonoBehaviours; using NitroxModel.DataStructures; using NitroxModel.Packets; @@ -9,12 +7,10 @@ namespace NitroxClient.Communication.Packets.Processors; public class SimulationOwnershipChangeProcessor : ClientPacketProcessor { - private readonly IMultiplayerSession multiplayerSession; private readonly SimulationOwnership simulationOwnershipManager; - public SimulationOwnershipChangeProcessor(IMultiplayerSession multiplayerSession, SimulationOwnership simulationOwnershipManager) + public SimulationOwnershipChangeProcessor(SimulationOwnership simulationOwnershipManager) { - this.multiplayerSession = multiplayerSession; this.simulationOwnershipManager = simulationOwnershipManager; } @@ -22,31 +18,7 @@ public override void Process(SimulationOwnershipChange simulationOwnershipChange { foreach (SimulatedEntity simulatedEntity in simulationOwnershipChange.Entities) { - if (multiplayerSession.Reservation.PlayerId == simulatedEntity.PlayerId) - { - if (simulatedEntity.ChangesPosition) - { - EntityPositionBroadcaster.WatchEntity(simulatedEntity.Id); - } - - simulationOwnershipManager.SimulateEntity(simulatedEntity.Id, simulatedEntity.LockType); - } - else if (simulationOwnershipManager.HasAnyLockType(simulatedEntity.Id)) - { - // The server has forcibly removed this lock from the client. This is generally fine for - // transient locks because it is only broadcasting position. However, exclusive locks may - // need additional cleanup (such as a person piloting a vehicle - they need to be kicked out) - // We can later add a forcibly removed callback but as of right now we have no use-cases for - // forcibly removing an exclusive lock. Just log it if it happens.... - - if (simulationOwnershipManager.HasExclusiveLock(simulatedEntity.Id)) - { - Log.Warn($"The server has forcibly revoked an exlusive lock - this may cause undefined behaviour. GUID: {simulatedEntity.Id}"); - } - - simulationOwnershipManager.StopSimulatingEntity(simulatedEntity.Id); - EntityPositionBroadcaster.StopWatchingEntity(simulatedEntity.Id); - } + simulationOwnershipManager.TreatSimulatedEntity(simulatedEntity); } } } diff --git a/NitroxClient/Communication/Packets/Processors/SpawnEntitiesProcessor.cs b/NitroxClient/Communication/Packets/Processors/SpawnEntitiesProcessor.cs index acb5e108e4..4fc26b996e 100644 --- a/NitroxClient/Communication/Packets/Processors/SpawnEntitiesProcessor.cs +++ b/NitroxClient/Communication/Packets/Processors/SpawnEntitiesProcessor.cs @@ -1,12 +1,6 @@ using NitroxClient.Communication.Packets.Processors.Abstract; using NitroxClient.GameLogic; -using NitroxClient.MonoBehaviours; -using NitroxModel.DataStructures.GameLogic; -using NitroxModel.DataStructures.Util; using NitroxModel.Packets; -using System.Collections.Generic; -using UnityEngine; -using UWE; namespace NitroxClient.Communication.Packets.Processors; @@ -23,24 +17,13 @@ public override void Process(SpawnEntities packet) { if (packet.ForceRespawn) { - CleanupExistingEntities(packet.Entities); + entities.CleanupExistingEntities(packet.Entities); } - CoroutineHost.StartCoroutine(entities.SpawnAsync(packet.Entities)); - } - - private void CleanupExistingEntities(List dirtyEntities) - { - foreach (Entity entity in dirtyEntities) + if (packet.Entities.Count > 0) { - entities.RemoveEntityHierarchy(entity); - - Optional gameObject = NitroxEntity.GetObjectFrom(entity.Id); - - if (gameObject.HasValue) - { - UnityEngine.Object.Destroy(gameObject.Value); - } + // Packet processing is done in the main thread so there's no issue calling this + entities.EnqueueEntitiesToSpawn(packet.Entities); } } } diff --git a/NitroxClient/Communication/Packets/Processors/ToggleLightsProcessor.cs b/NitroxClient/Communication/Packets/Processors/ToggleLightsProcessor.cs index 0a6fbcbc6a..6ee9c9448b 100644 --- a/NitroxClient/Communication/Packets/Processors/ToggleLightsProcessor.cs +++ b/NitroxClient/Communication/Packets/Processors/ToggleLightsProcessor.cs @@ -1,36 +1,53 @@ -using NitroxClient.Communication.Abstract; using NitroxClient.Communication.Packets.Processors.Abstract; using NitroxClient.GameLogic.FMOD; using NitroxClient.MonoBehaviours; using NitroxClient.Unity.Helper; +using NitroxModel.GameLogic.FMOD; using UnityEngine; -namespace NitroxClient.Communication.Packets.Processors +namespace NitroxClient.Communication.Packets.Processors; + +public class ToggleLightsProcessor : ClientPacketProcessor { - class ToggleLightsProcessor : ClientPacketProcessor + private readonly FMODWhitelist fmodWhitelist; + + public ToggleLightsProcessor(FMODWhitelist fmodWhitelist) + { + this.fmodWhitelist = fmodWhitelist; + } + + public override void Process(NitroxModel.Packets.ToggleLights packet) { - private readonly IPacketSender packetSender; + GameObject gameObject = NitroxEntity.RequireObjectFrom(packet.Id); + ToggleLights toggleLights = gameObject.RequireComponent(); - public ToggleLightsProcessor(IPacketSender packetSender) + if (packet.IsOn == toggleLights.GetLightsActive()) { - this.packetSender = packetSender; + return; } - public override void Process(NitroxModel.Packets.ToggleLights packet) + + using (PacketSuppressor.Suppress()) + using (FMODSystem.SuppressSendingSounds()) { - GameObject gameObject = NitroxEntity.RequireObjectFrom(packet.Id); - ToggleLights toggleLights = gameObject.GetComponent(); - if (!toggleLights) + using (FMODSystem.SuppressSubnauticaSounds()) + { + toggleLights.SetLightsActive(packet.IsOn); + } + + FMODAsset soundAsset; + + if (packet.IsOn) + { + soundAsset = toggleLights.lightsOnSound ? toggleLights.lightsOnSound.asset : toggleLights.onSound; + } + else { - toggleLights = gameObject.RequireComponentInChildren(); + soundAsset = toggleLights.lightsOffSound ? toggleLights.lightsOffSound.asset : toggleLights.offSound; } - if (packet.IsOn != toggleLights.GetLightsActive()) + if (soundAsset && fmodWhitelist.TryGetSoundData(soundAsset.path, out SoundData soundData)) { - using (PacketSuppressor.Suppress()) - using (FMODSystem.SuppressSounds()) - { - toggleLights.SetLightsActive(packet.IsOn); - } + FMODEmitterController.PlayEventOneShot(soundAsset, soundData.Radius, toggleLights.transform.position); } } } diff --git a/NitroxClient/Communication/Packets/Processors/VehicleDockingProcessor.cs b/NitroxClient/Communication/Packets/Processors/VehicleDockingProcessor.cs index 5031f2f62b..96bf72c97e 100644 --- a/NitroxClient/Communication/Packets/Processors/VehicleDockingProcessor.cs +++ b/NitroxClient/Communication/Packets/Processors/VehicleDockingProcessor.cs @@ -1,4 +1,4 @@ -using System.Collections; +using System.Collections; using NitroxClient.Communication.Abstract; using NitroxClient.Communication.Packets.Processors.Abstract; using NitroxClient.GameLogic; @@ -25,7 +25,7 @@ public override void Process(VehicleDocking packet) { GameObject vehicleGo = NitroxEntity.RequireObjectFrom(packet.VehicleId); GameObject vehicleDockingBayGo = NitroxEntity.RequireObjectFrom(packet.DockId); - +#if SUBNAUTICA Vehicle vehicle = vehicleGo.RequireComponent(); VehicleDockingBay vehicleDockingBay = vehicleDockingBayGo.RequireComponent(); @@ -36,15 +36,35 @@ public override void Process(VehicleDocking packet) vehicle.GetComponent().Exit(); } vehicle.StartCoroutine(DelayAnimationAndDisablePiloting(vehicle, vehicleDockingBay, packet.VehicleId, packet.PlayerId)); +#elif BELOWZERO + Dockable dockable = vehicleGo.RequireComponent(); + VehicleDockingBay vehicleDockingBay = vehicleDockingBayGo.RequireComponent(); + + using (PacketSuppressor.Suppress()) + { + Log.Debug($"Set docked for {vehicleDockingBay.gameObject.name}"); + dockable.GetComponent().SetPositionVelocityRotation(dockable.transform.position, Vector3.zero, dockable.transform.rotation, Vector3.zero); + dockable.GetComponent().Exit(); + } + dockable.StartCoroutine(DelayAnimationAndDisablePiloting(dockable, vehicleDockingBay, packet.VehicleId, packet.PlayerId)); +#endif } +#if SUBNAUTICA IEnumerator DelayAnimationAndDisablePiloting(Vehicle vehicle, VehicleDockingBay vehicleDockingBay, NitroxId vehicleId, ushort playerId) +#elif BELOWZERO + IEnumerator DelayAnimationAndDisablePiloting(Dockable vehicle, VehicleDockingBay vehicleDockingBay, NitroxId vehicleId, ushort playerId) +#endif { yield return Yielders.WaitFor1Second; // DockVehicle sets the rigid body kinematic of the vehicle to true, we don't want that behaviour // Therefore disable kinematic (again) to remove the bouncing behavior +#if SUBNAUTICA vehicleDockingBay.DockVehicle(vehicle); vehicle.useRigidbody.isKinematic = false; +#elif BELOWZERO + vehicleDockingBay.Dock(vehicle); +#endif yield return Yielders.WaitFor2Seconds; vehicles.SetOnPilotMode(vehicleId, playerId, false); if (!vehicle.docked) diff --git a/NitroxClient/Communication/Packets/Processors/VehicleUndockingProcessor.cs b/NitroxClient/Communication/Packets/Processors/VehicleUndockingProcessor.cs index 2f216ab825..dbe69142a4 100644 --- a/NitroxClient/Communication/Packets/Processors/VehicleUndockingProcessor.cs +++ b/NitroxClient/Communication/Packets/Processors/VehicleUndockingProcessor.cs @@ -1,4 +1,4 @@ -using System.Collections; +using System.Collections; using NitroxClient.Communication.Abstract; using NitroxClient.Communication.Packets.Processors.Abstract; using NitroxClient.GameLogic; @@ -58,7 +58,9 @@ private void StartVehicleUndocking(VehicleUndocking packet, GameObject vehicleGo // It can happen that the player turns in circles around himself in the vehicle. This stops it. playerInstance.RigidBody.angularVelocity = Vector3.zero; playerInstance.ArmsController.SetWorldIKTarget(vehicle.leftHandPlug, vehicle.rightHandPlug); +#if SUBNAUTICA playerInstance.AnimationController["in_seamoth"] = vehicle is SeaMoth; +#endif playerInstance.AnimationController["in_exosuit"] = playerInstance.AnimationController["using_mechsuit"] = vehicle is Exosuit; vehicles.SetOnPilotMode(packet.VehicleId, packet.PlayerId, true); playerInstance.AnimationController.UpdatePlayerAnimations = false; @@ -69,7 +71,11 @@ private void StartVehicleUndocking(VehicleUndocking packet, GameObject vehicleGo public IEnumerator StartUndockingAnimation(VehicleDockingBay vehicleDockingBay) { yield return Yielders.WaitFor2Seconds; +#if SUBNAUTICA vehicleDockingBay.vehicle_docked_param = false; +#elif BELOWZERO + vehicleDockingBay.docked_param = false; +#endif } private void FinishVehicleUndocking(VehicleUndocking packet, Vehicle vehicle, VehicleDockingBay vehicleDockingBay) @@ -78,7 +84,11 @@ private void FinishVehicleUndocking(VehicleUndocking packet, Vehicle vehicle, Ve { vehicleDockingBay.SetVehicleUndocked(); } +#if SUBNAUTICA vehicleDockingBay.dockedVehicle = null; +#elif BELOWZERO + vehicleDockingBay.dockedObject = null; +#endif vehicleDockingBay.CancelInvoke("RepairVehicle"); vehicle.docked = false; Optional player = remotePlayerManager.Find(packet.PlayerId); diff --git a/NitroxClient/Debuggers/Drawer/DrawerManager.cs b/NitroxClient/Debuggers/Drawer/DrawerManager.cs new file mode 100644 index 0000000000..fffe2e7791 --- /dev/null +++ b/NitroxClient/Debuggers/Drawer/DrawerManager.cs @@ -0,0 +1,147 @@ +using System; +using System.Collections.Generic; +using NitroxClient.Debuggers.Drawer.Nitrox; +using NitroxClient.Debuggers.Drawer.Subnautica; +using NitroxClient.Debuggers.Drawer.Unity; +using NitroxClient.Debuggers.Drawer.UnityUI; +using NitroxClient.MonoBehaviours; +using NitroxModel.DataStructures; +using NitroxModel.DataStructures.Unity; +using NitroxModel.Helper; +using UnityEngine; +using UnityEngine.Events; +using UnityEngine.UI; + +namespace NitroxClient.Debuggers.Drawer; + +/// +/// Registers known drawers into lookup dictionaries that are searched when and +/// are called. +/// +public class DrawerManager +{ + private readonly Dictionary> drawers = new(); + private readonly Dictionary> editorDrawers = new(); + + public DrawerManager(SceneDebugger sceneDebugger) + { + Validate.NotNull(sceneDebugger); + + ColorDrawer colorDrawer = new(); + UnityEventDrawer unityEventDrawer = new(); + SelectableDrawer selectableDrawer = new(sceneDebugger, colorDrawer); + VectorDrawer vectorDrawer = new(); + RectDrawer rectDrawer = new(); + LayoutGroupDrawer layoutGroupDrawer = new(rectDrawer); + MaterialDrawer materialDrawer = new(); + NitroxEntityDrawer nitroxEntityDrawer = new(); + + AddDrawer(nitroxEntityDrawer); + AddDrawer(nitroxEntityDrawer); + AddDrawer(); + AddDrawer(); + AddDrawer(new(selectableDrawer, unityEventDrawer)); + AddDrawer(new(sceneDebugger)); + AddDrawer(); + AddDrawer(); + AddDrawer(new(vectorDrawer)); + AddDrawer(); + AddDrawer(new(sceneDebugger, selectableDrawer)); + AddDrawer(); + AddDrawer(new(vectorDrawer, rectDrawer)); + AddDrawer(layoutGroupDrawer); + AddDrawer(layoutGroupDrawer); + AddDrawer(); + AddDrawer(new(vectorDrawer)); + AddDrawer(new(sceneDebugger, selectableDrawer)); + AddDrawer(new(sceneDebugger)); + AddDrawer(selectableDrawer); + AddDrawer(new(sceneDebugger, selectableDrawer)); + AddDrawer(new(colorDrawer, materialDrawer)); + AddDrawer(new(sceneDebugger, selectableDrawer, unityEventDrawer)); + AddDrawer(); + AddDrawer(new(vectorDrawer)); + AddDrawer(new(sceneDebugger, vectorDrawer)); + AddDrawer(unityEventDrawer); + AddDrawer>(unityEventDrawer); + AddDrawer(); + + AddEditor(vectorDrawer); + AddEditor(vectorDrawer); + AddEditor(vectorDrawer); + AddEditor(vectorDrawer); + AddEditor(vectorDrawer); + AddEditor(vectorDrawer); + AddEditor(vectorDrawer); + AddEditor(colorDrawer); + AddEditor(colorDrawer); + AddEditor(materialDrawer); + AddEditor(rectDrawer); + AddEditor(rectDrawer); + } + + /// + /// Tries to draw the item given its type. If item is null, returns false and does nothing. + /// + /// True if a drawer is known for the given item type. + public bool TryDraw(T item) + { + if (item == null) + { + return false; + } + if (!drawers.TryGetValue(item.GetType(), out IDrawer drawer)) + { + return false; + } + drawer.Draw(item); + return true; + } + + /// + /// Tries to draw the editor given the type of item. If item is null, returns false and does nothing. + /// + /// Item to draw the editor for. + /// Changed result from the editor. + /// True if an editor is known for the given item type. + public bool TryDrawEditor(T item, out T result) + { + if (item == null) + { + result = default; + return false; + } + if (!editorDrawers.TryGetValue(item.GetType(), out IEditorDrawer drawer)) + { + result = default; + return false; + } + result = (T)drawer.Draw(item); + return true; + } + + private void AddDrawer(TDrawer drawer) where TDrawer : IDrawer + { + drawers.Add(typeof(TDrawable), new DrawerWrapper(drawer)); + } + + private void AddDrawer() where TDrawer : IDrawer, new() + { + drawers.Add(typeof(TDrawable), new DrawerWrapper(new TDrawer())); + } + + private void AddEditor(TDrawer drawer) where TDrawer : IEditorDrawer + { + editorDrawers.Add(typeof(TDrawable), new EditorDrawerWrapper(drawer)); + } + + private class DrawerWrapper(IDrawer inner) : IDrawer + { + public void Draw(object target) => inner.Draw((T)target); + } + + private class EditorDrawerWrapper(IEditorDrawer inner) : IEditorDrawer + { + public object Draw(object target) => inner.Draw((T)target); + } +} diff --git a/NitroxClient/Debuggers/Drawer/IDrawer.cs b/NitroxClient/Debuggers/Drawer/IDrawer.cs index aa87c40b10..6c501da55f 100644 --- a/NitroxClient/Debuggers/Drawer/IDrawer.cs +++ b/NitroxClient/Debuggers/Drawer/IDrawer.cs @@ -1,15 +1,11 @@ -using System; - namespace NitroxClient.Debuggers.Drawer; -public interface IDrawer +public interface IDrawer { - public Type[] ApplicableTypes { get; } - public void Draw(object target); + void Draw(T target); } -public interface IStructDrawer +public interface IDrawer : IDrawer where TDrawOptions : class { - public Type[] ApplicableTypes { get; } - public object Draw(object target); + void Draw(T target, TDrawOptions options); } diff --git a/NitroxClient/Debuggers/Drawer/IEditorDrawer.cs b/NitroxClient/Debuggers/Drawer/IEditorDrawer.cs new file mode 100644 index 0000000000..dfba0934b2 --- /dev/null +++ b/NitroxClient/Debuggers/Drawer/IEditorDrawer.cs @@ -0,0 +1,11 @@ +namespace NitroxClient.Debuggers.Drawer; + +public interface IEditorDrawer +{ + T Draw(T target); +} + +public interface IEditorDrawer : IEditorDrawer where TDrawOptions : class +{ + T Draw(T target, TDrawOptions options); +} diff --git a/NitroxClient/Debuggers/Drawer/Nitrox/NitroxEntityDrawer.cs b/NitroxClient/Debuggers/Drawer/Nitrox/NitroxEntityDrawer.cs index ddaf68b147..03709b69c3 100644 --- a/NitroxClient/Debuggers/Drawer/Nitrox/NitroxEntityDrawer.cs +++ b/NitroxClient/Debuggers/Drawer/Nitrox/NitroxEntityDrawer.cs @@ -1,33 +1,17 @@ -using System; -using System.Linq; +using System.Linq; using NitroxClient.MonoBehaviours; using NitroxModel.DataStructures; using UnityEngine; namespace NitroxClient.Debuggers.Drawer.Nitrox; -public class NitroxEntityDrawer : IDrawer +public class NitroxEntityDrawer : IDrawer, IDrawer { private const float LABEL_WIDTH = 250; - public Type[] ApplicableTypes { get; } = { typeof(NitroxEntity), typeof(NitroxId) }; - - public void Draw(object target) - { - switch (target) - { - case NitroxEntity nitroxEntity: - DrawNitroxEntity(nitroxEntity); - break; - case NitroxId nitroxId: - DrawNitroxId(nitroxId); - break; - } - } - - private static void DrawNitroxEntity(NitroxEntity nitroxEntity) + public void Draw(NitroxEntity nitroxEntity) { - DrawNitroxId(nitroxEntity.Id); + Draw(nitroxEntity.Id); GUILayout.Space(8); @@ -39,7 +23,7 @@ private static void DrawNitroxEntity(NitroxEntity nitroxEntity) } } - private static void DrawNitroxId(NitroxId nitroxId) + public void Draw(NitroxId nitroxId) { using (new GUILayout.HorizontalScope()) { diff --git a/NitroxClient/Debuggers/Drawer/Subnautica/FMODAssetDrawer.cs b/NitroxClient/Debuggers/Drawer/Subnautica/FMODAssetDrawer.cs new file mode 100644 index 0000000000..9dab286338 --- /dev/null +++ b/NitroxClient/Debuggers/Drawer/Subnautica/FMODAssetDrawer.cs @@ -0,0 +1,11 @@ +using UnityEngine; + +namespace NitroxClient.Debuggers.Drawer.Subnautica; + +public class FMODAssetDrawer : IDrawer +{ + public void Draw(FMODAsset asset) + { + GUILayout.TextField(asset ? asset.path : "NULL"); + } +} diff --git a/NitroxClient/Debuggers/Drawer/Unity/ColorDrawer.cs b/NitroxClient/Debuggers/Drawer/Unity/ColorDrawer.cs index 68e01e7d88..fdd1dacb49 100644 --- a/NitroxClient/Debuggers/Drawer/Unity/ColorDrawer.cs +++ b/NitroxClient/Debuggers/Drawer/Unity/ColorDrawer.cs @@ -1,26 +1,15 @@ -using System; -using UnityEngine; +using UnityEngine; namespace NitroxClient.Debuggers.Drawer.Unity; -public class ColorDrawer : IStructDrawer +public class ColorDrawer : IEditorDrawer, IEditorDrawer { - public Type[] ApplicableTypes { get; } = { typeof(Color), typeof(Color32) }; - private static readonly Texture2D tex = new((int)NitroxGUILayout.VALUE_WIDTH, 25); private static Color lastColor; - public object Draw(object target) - { - return target switch - { - Color color => Draw(color), - Color32 color32 => (Color32) Draw(color32), - _ => null - }; - } + public Color32 Draw(Color32 color) => Draw((Color)color); - public static Color Draw(Color color) + public Color Draw(Color color) { if (color != lastColor) { diff --git a/NitroxClient/Debuggers/Drawer/Unity/MaterialDrawer.cs b/NitroxClient/Debuggers/Drawer/Unity/MaterialDrawer.cs index dca18fa780..9125119f8c 100644 --- a/NitroxClient/Debuggers/Drawer/Unity/MaterialDrawer.cs +++ b/NitroxClient/Debuggers/Drawer/Unity/MaterialDrawer.cs @@ -1,23 +1,10 @@ -using System; -using UnityEngine; +using UnityEngine; namespace NitroxClient.Debuggers.Drawer.Unity; -public class MaterialDrawer : IDrawer +public class MaterialDrawer : IEditorDrawer { - public Type[] ApplicableTypes { get; } = { typeof(Material) }; - - public void Draw(object target) - { - switch (target) - { - case Material material: - Draw(material); - break; - } - } - - public static Material Draw(Material material) + public Material Draw(Material material) { // TODO: Implement Material picker GUILayout.Box(material.name, GUILayout.Width(150), GUILayout.Height(20)); diff --git a/NitroxClient/Debuggers/Drawer/Unity/RectDrawer.cs b/NitroxClient/Debuggers/Drawer/Unity/RectDrawer.cs index 7fea1f185f..b1d61f955c 100644 --- a/NitroxClient/Debuggers/Drawer/Unity/RectDrawer.cs +++ b/NitroxClient/Debuggers/Drawer/Unity/RectDrawer.cs @@ -1,23 +1,16 @@ -using System; -using UnityEngine; +using UnityEngine; namespace NitroxClient.Debuggers.Drawer.Unity; -public class RectDrawer : IStructDrawer +public class RectDrawer : IEditorDrawer, IEditorDrawer { - public Type[] ApplicableTypes { get; } = { typeof(Rect) }; + private const float MAX_WIDTH = 400; - public object Draw(object target) + public Rect Draw(Rect rect, DrawOptions options) { - return target switch - { - Rect rect => DrawRect(rect), - _ => null - }; - } + options ??= new DrawOptions(); + var (valueWidth, maxWidth) = (options.Width, options.MaxWidth); - public static Rect DrawRect(Rect rect, float valueWidth = 100, float maxWidth = 215) - { using (new GUILayout.HorizontalScope(GUILayout.MaxWidth(maxWidth))) { using (new GUILayout.VerticalScope()) @@ -53,4 +46,34 @@ public static Rect DrawRect(Rect rect, float valueWidth = 100, float maxWidth = return rect; } + + public Rect Draw(Rect rect) + { + return Draw(rect, null); + } + + public RectOffset Draw(RectOffset rect, DrawOptions options) + { + options ??= new DrawOptions(Width: MAX_WIDTH); + + float valueWidth = options.MaxWidth / 4 - 6; + using (new GUILayout.HorizontalScope(GUILayout.MaxWidth(options.MaxWidth))) + { + rect.left = NitroxGUILayout.IntField(rect.left, valueWidth); + NitroxGUILayout.Separator(); + rect.right = NitroxGUILayout.IntField(rect.right, valueWidth); + NitroxGUILayout.Separator(); + rect.top = NitroxGUILayout.IntField(rect.top, valueWidth); + NitroxGUILayout.Separator(); + rect.bottom = NitroxGUILayout.IntField(rect.bottom, valueWidth); + } + return rect; + } + + public RectOffset Draw(RectOffset rect) + { + return Draw(rect, null); + } + + public record DrawOptions(float Width = 100, float MaxWidth = 215); } diff --git a/NitroxClient/Debuggers/Drawer/Unity/RigidbodyDrawer.cs b/NitroxClient/Debuggers/Drawer/Unity/RigidbodyDrawer.cs index df8e68f2ae..3d780a69d4 100644 --- a/NitroxClient/Debuggers/Drawer/Unity/RigidbodyDrawer.cs +++ b/NitroxClient/Debuggers/Drawer/Unity/RigidbodyDrawer.cs @@ -1,109 +1,109 @@ -using System; +using NitroxModel.Helper; using UnityEngine; -namespace NitroxClient.Debuggers.Drawer.Unity +namespace NitroxClient.Debuggers.Drawer.Unity; + +public class RigidbodyDrawer : IDrawer { - /// - /// Draws a Rigidbody component on the gameobjects in the - /// - public class RigidbodyDrawer : IDrawer + private readonly VectorDrawer vectorDrawer; + private const float LABEL_WIDTH = 120; + private const float VALUE_MAX_WIDTH = 405; + + public RigidbodyDrawer(VectorDrawer vectorDrawer) + { + Validate.NotNull(vectorDrawer); + + this.vectorDrawer = vectorDrawer; + } + + public void Draw(Rigidbody rb) { - private const float LABEL_WIDTH = 120; - private const float VALUE_MAX_WIDTH = 405; + using (new GUILayout.HorizontalScope()) + { + GUILayout.Label("Mass", NitroxGUILayout.DrawerLabel, GUILayout.Width(LABEL_WIDTH)); + NitroxGUILayout.Separator(); + rb.mass = NitroxGUILayout.FloatField(rb.mass, VALUE_MAX_WIDTH); + } + + GUILayout.Space(10); + + using (new GUILayout.HorizontalScope()) + { + GUILayout.Label("Drag", NitroxGUILayout.DrawerLabel, GUILayout.Width(LABEL_WIDTH)); + NitroxGUILayout.Separator(); + rb.drag = NitroxGUILayout.FloatField(rb.drag, VALUE_MAX_WIDTH); + } + + GUILayout.Space(10); + + using (new GUILayout.HorizontalScope()) + { + GUILayout.Label("Angular Drag", NitroxGUILayout.DrawerLabel, GUILayout.Width(LABEL_WIDTH)); + NitroxGUILayout.Separator(); + rb.angularDrag = NitroxGUILayout.FloatField(rb.angularDrag, VALUE_MAX_WIDTH); + } + + GUILayout.Space(10); + + using (new GUILayout.HorizontalScope()) + { + GUILayout.Label("Use Gravity"); + NitroxGUILayout.Separator(); + rb.useGravity = NitroxGUILayout.BoolField(rb.useGravity); + } + + GUILayout.Space(10); + + using (new GUILayout.HorizontalScope()) + { + GUILayout.Label("Is Kinematic"); + NitroxGUILayout.Separator(); + rb.isKinematic = NitroxGUILayout.BoolField(rb.isKinematic); + } + + GUILayout.Space(10); + + using (new GUILayout.HorizontalScope()) + { + GUILayout.Label("Interpolate", GUILayout.Width(LABEL_WIDTH)); + NitroxGUILayout.Separator(); + rb.interpolation = NitroxGUILayout.EnumPopup(rb.interpolation, NitroxGUILayout.VALUE_WIDTH); + } + + GUILayout.Space(10); + + using (new GUILayout.HorizontalScope()) + { + GUILayout.Label("Collision Detection", GUILayout.Width(LABEL_WIDTH)); + NitroxGUILayout.Separator(); + rb.collisionDetectionMode = NitroxGUILayout.EnumPopup(rb.collisionDetectionMode, NitroxGUILayout.VALUE_WIDTH); + } + + GUILayout.Space(10); + + using (new GUILayout.HorizontalScope()) + { + GUILayout.Label("Freeze Rotation"); + NitroxGUILayout.Separator(); + rb.freezeRotation = NitroxGUILayout.BoolField(rb.freezeRotation); + } + + GUILayout.Space(10); + + using (new GUILayout.HorizontalScope()) + { + GUILayout.Label("Velocity", NitroxGUILayout.DrawerLabel, GUILayout.Width(LABEL_WIDTH)); + NitroxGUILayout.Separator(); + vectorDrawer.Draw(rb.velocity, new VectorDrawer.DrawOptions(VALUE_MAX_WIDTH)); + } - public Type[] ApplicableTypes => new[] { typeof(Rigidbody) }; + GUILayout.Space(10); - public void Draw(object target) + using (new GUILayout.HorizontalScope()) { - Rigidbody rb = (Rigidbody)target; - - using (new GUILayout.HorizontalScope()) - { - GUILayout.Label("Mass", NitroxGUILayout.DrawerLabel, GUILayout.Width(LABEL_WIDTH)); - NitroxGUILayout.Separator(); - rb.mass = NitroxGUILayout.FloatField(rb.mass, VALUE_MAX_WIDTH); - } - - GUILayout.Space(10); - - using (new GUILayout.HorizontalScope()) - { - GUILayout.Label("Drag", NitroxGUILayout.DrawerLabel, GUILayout.Width(LABEL_WIDTH)); - NitroxGUILayout.Separator(); - rb.drag = NitroxGUILayout.FloatField(rb.drag, VALUE_MAX_WIDTH); - } - - GUILayout.Space(10); - - using (new GUILayout.HorizontalScope()) - { - GUILayout.Label("Angular Drag", NitroxGUILayout.DrawerLabel, GUILayout.Width(LABEL_WIDTH)); - NitroxGUILayout.Separator(); - rb.angularDrag = NitroxGUILayout.FloatField(rb.angularDrag, VALUE_MAX_WIDTH); - } - - GUILayout.Space(10); - - using (new GUILayout.HorizontalScope()) - { - GUILayout.Label("Use Gravity"); - NitroxGUILayout.Separator(); - rb.useGravity = NitroxGUILayout.BoolField(rb.useGravity); - } - - GUILayout.Space(10); - - using (new GUILayout.HorizontalScope()) - { - GUILayout.Label("Is Kinematic"); - NitroxGUILayout.Separator(); - rb.isKinematic = NitroxGUILayout.BoolField(rb.isKinematic); - } - - GUILayout.Space(10); - - using (new GUILayout.HorizontalScope()) - { - GUILayout.Label("Interpolate", GUILayout.Width(LABEL_WIDTH)); - NitroxGUILayout.Separator(); - rb.interpolation = NitroxGUILayout.EnumPopup(rb.interpolation, NitroxGUILayout.VALUE_WIDTH); - } - - GUILayout.Space(10); - - using (new GUILayout.HorizontalScope()) - { - GUILayout.Label("Collision Detection", GUILayout.Width(LABEL_WIDTH)); - NitroxGUILayout.Separator(); - rb.collisionDetectionMode = NitroxGUILayout.EnumPopup(rb.collisionDetectionMode, NitroxGUILayout.VALUE_WIDTH); - } - - GUILayout.Space(10); - - using (new GUILayout.HorizontalScope()) - { - GUILayout.Label("Freeze Rotation"); - NitroxGUILayout.Separator(); - rb.freezeRotation = NitroxGUILayout.BoolField(rb.freezeRotation); - } - - GUILayout.Space(10); - - using (new GUILayout.HorizontalScope()) - { - GUILayout.Label("Velocity", NitroxGUILayout.DrawerLabel, GUILayout.Width(LABEL_WIDTH)); - NitroxGUILayout.Separator(); - VectorDrawer.DrawVector3(rb.velocity, VALUE_MAX_WIDTH); - } - - GUILayout.Space(10); - - using (new GUILayout.HorizontalScope()) - { - GUILayout.Label("Angular Velocity", NitroxGUILayout.DrawerLabel, GUILayout.Width(LABEL_WIDTH)); - NitroxGUILayout.Separator(); - VectorDrawer.DrawVector3(rb.angularVelocity, VALUE_MAX_WIDTH); - } + GUILayout.Label("Angular Velocity", NitroxGUILayout.DrawerLabel, GUILayout.Width(LABEL_WIDTH)); + NitroxGUILayout.Separator(); + vectorDrawer.Draw(rb.angularVelocity, new VectorDrawer.DrawOptions(VALUE_MAX_WIDTH)); } } } diff --git a/NitroxClient/Debuggers/Drawer/Unity/TransformDrawer.cs b/NitroxClient/Debuggers/Drawer/Unity/TransformDrawer.cs index f2514e48e4..66a3239ab8 100644 --- a/NitroxClient/Debuggers/Drawer/Unity/TransformDrawer.cs +++ b/NitroxClient/Debuggers/Drawer/Unity/TransformDrawer.cs @@ -1,29 +1,27 @@ -using System; +using NitroxModel.Helper; using UnityEngine; namespace NitroxClient.Debuggers.Drawer.Unity; -public class TransformDrawer : IDrawer +public class TransformDrawer : IDrawer { + private readonly SceneDebugger sceneDebugger; + private readonly VectorDrawer vectorDrawer; private const float LABEL_WIDTH = 100; - private const float LABEL_SEPARATOR = 40; private const float VECTOR_MAX_WIDTH = 405; - public Type[] ApplicableTypes { get; } = { typeof(Transform) }; - private bool showGlobal; - public void Draw(object target) + public TransformDrawer(SceneDebugger sceneDebugger, VectorDrawer vectorDrawer) { - switch (target) - { - case Transform transform: - DrawTransform(transform); - break; - } + Validate.NotNull(sceneDebugger); + Validate.NotNull(vectorDrawer); + + this.sceneDebugger = sceneDebugger; + this.vectorDrawer = vectorDrawer; } - private void DrawTransform(Transform transform) + public void Draw(Transform transform) { using (new GUILayout.VerticalScope()) { @@ -33,21 +31,21 @@ private void DrawTransform(Transform transform) { GUILayout.Label("Global Position", NitroxGUILayout.DrawerLabel, GUILayout.Width(LABEL_WIDTH)); NitroxGUILayout.Separator(); - VectorDrawer.DrawVector3(transform.position, VECTOR_MAX_WIDTH); + vectorDrawer.Draw(transform.position, new VectorDrawer.DrawOptions(VECTOR_MAX_WIDTH)); } using (new GUILayout.HorizontalScope()) { GUILayout.Label("Global Rotation", NitroxGUILayout.DrawerLabel, GUILayout.Width(LABEL_WIDTH)); NitroxGUILayout.Separator(); - VectorDrawer.DrawVector3(transform.rotation.eulerAngles, VECTOR_MAX_WIDTH); + vectorDrawer.Draw(transform.rotation.eulerAngles, new VectorDrawer.DrawOptions(VECTOR_MAX_WIDTH)); } using (new GUILayout.HorizontalScope()) { GUILayout.Label("Lossy Scale", NitroxGUILayout.DrawerLabel, GUILayout.Width(LABEL_WIDTH)); NitroxGUILayout.Separator(); - VectorDrawer.DrawVector3(transform.lossyScale, VECTOR_MAX_WIDTH); + vectorDrawer.Draw(transform.lossyScale, new VectorDrawer.DrawOptions(VECTOR_MAX_WIDTH)); } } else @@ -56,29 +54,57 @@ private void DrawTransform(Transform transform) { GUILayout.Label("Local Position", NitroxGUILayout.DrawerLabel, GUILayout.Width(LABEL_WIDTH)); NitroxGUILayout.Separator(); - transform.localPosition = VectorDrawer.DrawVector3(transform.localPosition, VECTOR_MAX_WIDTH); + transform.localPosition = vectorDrawer.Draw(transform.localPosition, new VectorDrawer.DrawOptions(VECTOR_MAX_WIDTH)); } using (new GUILayout.HorizontalScope()) { GUILayout.Label("Local Rotation", NitroxGUILayout.DrawerLabel, GUILayout.Width(LABEL_WIDTH)); NitroxGUILayout.Separator(); - transform.localRotation = Quaternion.Euler(VectorDrawer.DrawVector3(transform.localRotation.eulerAngles, VECTOR_MAX_WIDTH)); + transform.localRotation = Quaternion.Euler(vectorDrawer.Draw(transform.localRotation.eulerAngles, new VectorDrawer.DrawOptions(VECTOR_MAX_WIDTH))); } using (new GUILayout.HorizontalScope()) { GUILayout.Label("Local Scale", NitroxGUILayout.DrawerLabel, GUILayout.Width(LABEL_WIDTH)); NitroxGUILayout.Separator(); - transform.localScale = VectorDrawer.DrawVector3(transform.localScale, VECTOR_MAX_WIDTH); + transform.localScale = vectorDrawer.Draw(transform.localScale, new VectorDrawer.DrawOptions(VECTOR_MAX_WIDTH)); } } GUILayout.Space(5); - if (GUILayout.Button("Toggle Local/Global", GUILayout.MaxWidth(125))) + using (new GUILayout.HorizontalScope()) { - showGlobal = !showGlobal; + if (GUILayout.Button("Toggle Local/Global", GUILayout.MaxWidth(125))) + { + showGlobal = !showGlobal; + } + if (GUILayout.Button("Destroy GameObject", GUILayout.MaxWidth(150))) + { + if (transform) + { + if (transform.parent) + { + sceneDebugger.JumpToComponent(transform.parent); + } + UnityEngine.Object.Destroy(transform.gameObject); + } + } + if (GUILayout.Button("Goto", GUILayout.MaxWidth(75)) && Player.main) + { + SubRoot subRoot = transform.GetComponentInParent(true); +#if SUBNAUTICA + Player.main.SetCurrentSub(subRoot, true); +#elif BELOWZERO + Player.main.SetCurrentSub(subRoot); +#endif + Player.main.SetPosition(transform.position); + } + if (GUILayout.Button($"Set {(transform.gameObject.activeSelf ? "inactive" : "active")}", GUILayout.MaxWidth(125))) + { + transform.gameObject.SetActive(!transform.gameObject.activeSelf); + } } } } diff --git a/NitroxClient/Debuggers/Drawer/Unity/UnityEventDrawer.cs b/NitroxClient/Debuggers/Drawer/Unity/UnityEventDrawer.cs index 96bd6b755d..e6d6225b9e 100644 --- a/NitroxClient/Debuggers/Drawer/Unity/UnityEventDrawer.cs +++ b/NitroxClient/Debuggers/Drawer/Unity/UnityEventDrawer.cs @@ -1,33 +1,19 @@ -using System; -using UnityEngine; +using UnityEngine; using UnityEngine.Events; namespace NitroxClient.Debuggers.Drawer.Unity; -public class UnityEventDrawer : IDrawer +public class UnityEventDrawer : IDrawer, IDrawer, UnityEventDrawer.DrawOptions> { private const float LABEL_WIDTH = 250; - public Type[] ApplicableTypes { get; } = { typeof(UnityEvent), typeof(UnityEvent) }; - - public void Draw(object target) + public void Draw(UnityEvent unityEvent, DrawOptions options) { - switch (target) - { - case UnityEvent unityEvent: - DrawUnityEvent(unityEvent); - break; - case UnityEvent unityEventBool: - DrawUnityEventBool(unityEventBool); - break; - } - } + options ??= new DrawOptions(); - public static void DrawUnityEvent(UnityEvent unityEvent, string name = "NoName") - { using (new GUILayout.HorizontalScope()) { - GUILayout.Label(name, NitroxGUILayout.DrawerLabel, GUILayout.Width(LABEL_WIDTH)); + GUILayout.Label(options.Name, NitroxGUILayout.DrawerLabel, GUILayout.Width(LABEL_WIDTH)); NitroxGUILayout.Separator(); if (GUILayout.Button("Invoke All", GUILayout.Width(100))) { @@ -38,11 +24,13 @@ public static void DrawUnityEvent(UnityEvent unityEvent, string name = "NoName") DrawUnityEventBase(unityEvent); } - public static void DrawUnityEventBool(UnityEvent unityEvent, string name = "NoName") + public void Draw(UnityEvent unityEvent, DrawOptions options) { + options ??= new DrawOptions(); + using (new GUILayout.HorizontalScope()) { - GUILayout.Label(name, NitroxGUILayout.DrawerLabel, GUILayout.Width(LABEL_WIDTH)); + GUILayout.Label(options.Name, NitroxGUILayout.DrawerLabel, GUILayout.Width(LABEL_WIDTH)); NitroxGUILayout.Separator(); if (GUILayout.Button("Invoke All (true)", GUILayout.Width(100))) { @@ -57,7 +45,7 @@ public static void DrawUnityEventBool(UnityEvent unityEvent, string name = DrawUnityEventBase(unityEvent); } - public static void DrawUnityEventBase(UnityEventBase unityEventBase) + private static void DrawUnityEventBase(UnityEventBase unityEventBase) { for (int index = 0; index < unityEventBase.GetPersistentEventCount(); index++) { @@ -68,4 +56,10 @@ public static void DrawUnityEventBase(UnityEventBase unityEventBase) } } } + + public record DrawOptions(string Name = "NoName"); + + public void Draw(UnityEvent unityEvent) => Draw(unityEvent, null); + + public void Draw(UnityEvent unityEvent) => Draw(unityEvent, null); } diff --git a/NitroxClient/Debuggers/Drawer/Unity/VectorDrawer.cs b/NitroxClient/Debuggers/Drawer/Unity/VectorDrawer.cs index bf9247d8cf..b8aebf1879 100644 --- a/NitroxClient/Debuggers/Drawer/Unity/VectorDrawer.cs +++ b/NitroxClient/Debuggers/Drawer/Unity/VectorDrawer.cs @@ -1,35 +1,20 @@ -using System; +using NitroxModel_Subnautica.DataStructures; using NitroxModel.DataStructures.Unity; -using NitroxModel_Subnautica.DataStructures; using UnityEngine; namespace NitroxClient.Debuggers.Drawer.Unity; -public class VectorDrawer : IStructDrawer +public class VectorDrawer : IEditorDrawer, IEditorDrawer, IEditorDrawer, IEditorDrawer, IEditorDrawer, IEditorDrawer, + IEditorDrawer { private const float MAX_WIDTH = 400; - public Type[] ApplicableTypes { get; } = { typeof(Vector2), typeof(Vector3), typeof(NitroxVector3), typeof(Vector4), typeof(NitroxVector4), typeof(Quaternion), typeof(Int3) }; - - public object Draw(object target) + public Vector2 Draw(Vector2 vector2, DrawOptions options) { - return target switch - { - Vector2 vector2 => DrawVector2(vector2), - Vector3 vector3 => DrawVector3(vector3), - NitroxVector3 nitroxVector3 => DrawVector3(nitroxVector3.ToUnity()).ToDto(), - Vector4 vector4 => DrawVector4(vector4), - NitroxVector4 nitroxVector4 => DrawVector4(nitroxVector4.ToUnity()).ToDto(), - Quaternion quaternion => DrawQuaternion(quaternion), - Int3 int3 => DrawInt3(int3), - _ => null - }; - } + options ??= new DrawOptions(); - public static Vector2 DrawVector2(Vector2 vector2, float maxWidth = MAX_WIDTH) - { - float valueWidth = maxWidth / 2 - 5; - using (new GUILayout.HorizontalScope(GUILayout.MaxWidth(maxWidth))) + float valueWidth = options.MaxWidth / 2 - 5; + using (new GUILayout.HorizontalScope(GUILayout.MaxWidth(options.MaxWidth))) { vector2.x = NitroxGUILayout.FloatField(vector2.x, valueWidth); NitroxGUILayout.Separator(); @@ -38,10 +23,12 @@ public static Vector2 DrawVector2(Vector2 vector2, float maxWidth = MAX_WIDTH) } } - public static Vector3 DrawVector3(Vector3 vector3, float maxWidth = MAX_WIDTH) + public Vector3 Draw(Vector3 vector3, DrawOptions options) { - float valueWidth = maxWidth / 3 - 5; - using (new GUILayout.HorizontalScope(GUILayout.MaxWidth(maxWidth))) + options ??= new DrawOptions(); + + float valueWidth = options.MaxWidth / 3 - 5; + using (new GUILayout.HorizontalScope(GUILayout.MaxWidth(options.MaxWidth))) { vector3.x = NitroxGUILayout.FloatField(vector3.x, valueWidth); NitroxGUILayout.Separator(); @@ -52,56 +39,62 @@ public static Vector3 DrawVector3(Vector3 vector3, float maxWidth = MAX_WIDTH) } } - public static Vector4 DrawVector4(Vector4 vector4, float maxWidth = MAX_WIDTH) + public Vector4 Draw(Vector4 vector) { - float valueWidth = maxWidth / 4 - 6; - using (new GUILayout.HorizontalScope(GUILayout.MaxWidth(maxWidth))) + float valueWidth = MAX_WIDTH / 4 - 6; + using (new GUILayout.HorizontalScope(GUILayout.MaxWidth(MAX_WIDTH))) { - vector4.x = NitroxGUILayout.FloatField(vector4.x, valueWidth); + vector.x = NitroxGUILayout.FloatField(vector.x, valueWidth); NitroxGUILayout.Separator(); - vector4.y = NitroxGUILayout.FloatField(vector4.y, valueWidth); + vector.y = NitroxGUILayout.FloatField(vector.y, valueWidth); NitroxGUILayout.Separator(); - vector4.z = NitroxGUILayout.FloatField(vector4.z, valueWidth); + vector.z = NitroxGUILayout.FloatField(vector.z, valueWidth); NitroxGUILayout.Separator(); - vector4.w = NitroxGUILayout.FloatField(vector4.w, valueWidth); - return vector4; + vector.w = NitroxGUILayout.FloatField(vector.w, valueWidth); + return vector; } } - public static Quaternion DrawQuaternion(Quaternion quaternion, float maxWidth = MAX_WIDTH) + public Quaternion Draw(Quaternion vector) { - Vector4 vector4 = new(quaternion.x, quaternion.y, quaternion.z, quaternion.w); - vector4 = DrawVector4(vector4, maxWidth); + Vector4 vector4 = new(vector.x, vector.y, vector.z, vector.w); + vector4 = Draw(vector4); return new Quaternion(vector4.x, vector4.y, vector4.z, vector4.w); } - public static Int3 DrawInt3(Int3 int3, float maxWidth = MAX_WIDTH) + public Int3 Draw(Int3 vector) { - float valueWidth = maxWidth / 3 - 5; - using (new GUILayout.HorizontalScope(GUILayout.MaxWidth(maxWidth))) + float valueWidth = MAX_WIDTH / 3 - 5; + using (new GUILayout.HorizontalScope(GUILayout.MaxWidth(MAX_WIDTH))) { - int3.x = NitroxGUILayout.IntField(int3.x, valueWidth); + vector.x = NitroxGUILayout.IntField(vector.x, valueWidth); NitroxGUILayout.Separator(); - int3.y = NitroxGUILayout.IntField(int3.y, valueWidth); + vector.y = NitroxGUILayout.IntField(vector.y, valueWidth); NitroxGUILayout.Separator(); - int3.z = NitroxGUILayout.IntField(int3.z, valueWidth); - return int3; + vector.z = NitroxGUILayout.IntField(vector.z, valueWidth); + return vector; } } - public static Tuple DrawInt4(int item1, int item2, int item3, int item4, float maxWidth = MAX_WIDTH) + public NitroxVector3 Draw(NitroxVector3 vector) { - float valueWidth = maxWidth / 4 - 6; - using (new GUILayout.HorizontalScope(GUILayout.MaxWidth(maxWidth))) - { - item1 = NitroxGUILayout.IntField(item1, valueWidth); - NitroxGUILayout.Separator(); - item2 = NitroxGUILayout.IntField(item2, valueWidth); - NitroxGUILayout.Separator(); - item4 = NitroxGUILayout.IntField(item4, valueWidth); - NitroxGUILayout.Separator(); - item4 = NitroxGUILayout.IntField(item4, valueWidth); - return new Tuple(item1, item2, item3, item4); - } + return Draw(vector.ToUnity()).ToDto(); + } + + public NitroxVector4 Draw(NitroxVector4 vector) + { + return Draw(vector.ToUnity()).ToDto(); + } + + public record DrawOptions(float MaxWidth = MAX_WIDTH); + + public Vector2 Draw(Vector2 vector) + { + return Draw(vector, null); + } + + public Vector3 Draw(Vector3 vector) + { + return Draw(vector, null); } } diff --git a/NitroxClient/Debuggers/Drawer/UnityUI/AnimatorDrawer.cs b/NitroxClient/Debuggers/Drawer/UnityUI/AnimatorDrawer.cs new file mode 100644 index 0000000000..5ea81d5c12 --- /dev/null +++ b/NitroxClient/Debuggers/Drawer/UnityUI/AnimatorDrawer.cs @@ -0,0 +1,55 @@ +using UnityEngine; + +namespace NitroxClient.Debuggers.Drawer.UnityUI; + +public class AnimatorDrawer : IDrawer +{ + public void Draw(Animator target) + { + using (new GUILayout.HorizontalScope()) + { + GUILayout.Label("updateMode", GUILayout.Width(200)); + target.updateMode = NitroxGUILayout.EnumPopup(target.updateMode, NitroxGUILayout.VALUE_WIDTH); + } + + GUILayout.Label($"Parameters [{target.parameterCount}]:"); + foreach (AnimatorControllerParameter parameter in target.parameters) + { + GUILayout.Space(8); + + using (new GUILayout.HorizontalScope()) + { + GUILayout.Label(parameter.name, GUILayout.Width(200)); + NitroxGUILayout.Separator(); + switch (parameter.type) + { + case AnimatorControllerParameterType.Float: + float floatValue = NitroxGUILayout.FloatField(target.GetFloat(parameter.name)); + + target.SetFloat(parameter.name, GUILayout.Button("Reset") ? parameter.defaultFloat : floatValue); + break; + case AnimatorControllerParameterType.Int: + int intValue = NitroxGUILayout.IntField(target.GetInteger(parameter.name)); + + target.SetInteger(parameter.name, GUILayout.Button("Reset") ? parameter.defaultInt : intValue); + break; + case AnimatorControllerParameterType.Bool: + bool boolValue = NitroxGUILayout.BoolField(target.GetBool(parameter.name)); + + target.SetBool(parameter.name, GUILayout.Button("Reset") ? parameter.defaultBool : boolValue); + break; + case AnimatorControllerParameterType.Trigger: + if (GUILayout.Button("Trigger")) + { + target.SetTrigger(parameter.name); + } + if (GUILayout.Button("Reset")) + { + target.ResetTrigger(parameter.name); + } + break; + } + } + } + } +} diff --git a/NitroxClient/Debuggers/Drawer/UnityUI/AspectRatioFitterDrawer.cs b/NitroxClient/Debuggers/Drawer/UnityUI/AspectRatioFitterDrawer.cs index ac14d69ec2..87d38e9396 100644 --- a/NitroxClient/Debuggers/Drawer/UnityUI/AspectRatioFitterDrawer.cs +++ b/NitroxClient/Debuggers/Drawer/UnityUI/AspectRatioFitterDrawer.cs @@ -1,24 +1,11 @@ -using System; -using UnityEngine; +using UnityEngine; using UnityEngine.UI; namespace NitroxClient.Debuggers.Drawer.UnityUI; -public class AspectRatioFitterDrawer : IDrawer +public class AspectRatioFitterDrawer : IDrawer { - public Type[] ApplicableTypes { get; } = { typeof(AspectRatioFitter) }; - - public void Draw(object target) - { - switch (target) - { - case AspectRatioFitter aspectRatioFitter: - DrawAspectRatioFitter(aspectRatioFitter); - break; - } - } - - private static void DrawAspectRatioFitter(AspectRatioFitter aspectRatioFitter) + public void Draw(AspectRatioFitter aspectRatioFitter) { using (new GUILayout.HorizontalScope()) { diff --git a/NitroxClient/Debuggers/Drawer/UnityUI/ButtonDrawer.cs b/NitroxClient/Debuggers/Drawer/UnityUI/ButtonDrawer.cs index 9c60de58e1..fb566158ca 100644 --- a/NitroxClient/Debuggers/Drawer/UnityUI/ButtonDrawer.cs +++ b/NitroxClient/Debuggers/Drawer/UnityUI/ButtonDrawer.cs @@ -1,28 +1,27 @@ -using System; -using NitroxClient.Debuggers.Drawer.Unity; +using NitroxClient.Debuggers.Drawer.Unity; +using NitroxModel.Helper; using UnityEngine; using UnityEngine.UI; namespace NitroxClient.Debuggers.Drawer.UnityUI; -public class ButtonDrawer : IDrawer +public class ButtonDrawer : IDrawer